问:
How to add path parameter in elasticsearch Java bulk Api
I'm using Java bulk Api,Elasticsearch 6.6.2, and expect to POST bulk request as

POST /<index>/_bulk,

but i got POST /_bulk instead (see packet captured below).

I know these 2 POST methods are the same, but there're a proxy between my app and ES, the path parameter is for the proxy for some reasons(I don't know why).

so, I wonder how to set the path parameter in Java ,so that request can be sent in POST /<index>/_bulk format.

Here's the code

```<code>        RestHighLevelClient client;
        /* some client init code ....*/
        ...
        String INDEX = "api_track";
        String DOC_TYPE = "_doc";

        BulkProcessor.Builder builder = BulkProcessor.builder(
                (request, bulkListener) ->
                        client.bulkAsync(request, RequestOptions.DEFAULT, bulkListener),
                listener);
        builder.setBulkActions(500);
        builder.setBulkSize(new ByteSizeValue(1L, ByteSizeUnit.MB));
        builder.setConcurrentRequests(0);
        builder.setFlushInterval(TimeValue.timeValueSeconds(5L));
        builder.setBackoffPolicy(BackoffPolicy
                .constantBackoff(TimeValue.timeValueSeconds(1L), 3));
        builder.setGlobalIndex(INDEX);
        builder.setGlobalType(DOC_TYPE);
        bulkProcessor = builder.build();

        IndexRequest request = new IndexRequest().index(INDEX).type(DOC_TYPE).source(maps);
        bulkProcessor.add(request);
</code>```

and the packet captured:

```<code>    0x0000:  0200 0000 4500 0277 0000 4000 4006 12c9  ....E..w..@.@...
    0x0010:  1e27 dee3 0ba3 1d0b e142 23f0 85d1 ad67  .'.......B#....g
    0x0020:  1540 31d3 8018 0801 3eb0 0000 0101 080a  .@1.....>.......
    0x0030:  1500 c5e6 b6ba 7ff0 504f 5354 202f 5f62  ........POST./_b   <-- POST format here
    0x0040:  756c 6b3f 7469 6d65 6f75 743d 316d 2048  ulk?timeout=1m.H
    0x0050:  5454 502f 312e 310d 0a43 6f6e 7465 6e74  TTP/1.1..Content
    0x0060:  2d4c 656e 6774 683a 2033 3335 0d0a 436f  -Length:.335..Co
    0x0070:  6e74 656e 742d 5479 7065 3a20 6170 706c  ntent-Type:.appl
    0x0080:  6963 6174 696f 6e2f 6a73 6f6e 0d0a 486f  ication/json..Ho
    0x0090:  7374 3a20 7365 6172 6368 2e61 6c69 7061  st:.search.alipa
    0x00a0:  792e 6e65 743a 3932 3030 0d0a 436f 6e6e  y.net:9200..Conn
    0x00b0:  6563 7469 6f6e 3a20 4b65 6570 2d41 6c69  ection:.Keep-Ali
    0x00c0:  7665 0d0a 5573 6572 2d41 6765 6e74 3a20  ve..User-Agent:.
    0x00d0:  4170 6163 6865 2d48 7474 7041 7379 6e63  Apache-HttpAsync
    0x00e0:  436c 6965 6e74 2f34 2e31 2e34 2028 4a61  Client/4.1.4.(Ja
    0x00f0:  7661 2f31 2e38 2e30 5f31 3531 290d 0a41  va/1.8.0_151)..A
    0x0100:  7574 686f 7269 7a61 7469 6f6e 3a20 4261  uthorization:.Ba
    0x0110:  7369 6320 6247 6c75 6132 4d36 527a 4e61  sic.bGlua2M6RzNa
    0x0120:  5954 4e4e 5755 593d 0d0a 0d0a 7b22 696e  YTNNWUY=....{"in
    0x0130:  6465 7822 3a7b 225f 696e 6465 7822 3a22  dex":{"_index":"
    0x0140:  6170 695f 7472 6163 6b22 2c22 5f74 7970  api_track","_typ
    0x0150:  6522 3a22 5f64 6f63 227d 7d0a 7b22 6372  e":"_doc"}}.{"cr
    0x0160:  6561 7465 6441 7422 3a22 3230 3230 2d30  eatedAt":"2020-0
    0x0170:  322d 3132 5430 383a 3438 3a34 332e 3333  2-12T08:48:43.33
    0x0180:  3822 2c22 686f 7374 4164 6472 223a 2231  8","hostAddr":"1
    0x0190:  3237 2e30 2e30 2e31 222c 2274 656e 616e  27.0.0.1","tenan
    0x01a0:  7449 6422 3a6e 756c 6c2c 2273 6572 7665  tId":null,"serve
    0x01b0:  724e 616d 6522 3a6e 756c 6c2c 2270 6172  rName":null,"par
    0x01c0:  616d 7322 3a22 2670 7269 7661 7465 5f74  ams":"&private_t
    0x01d0:  6f6b 656e 3d2a 2a2a 266f 7264 6572 5f62  oken=***&order_b
    0x01e0:  793d 7369 7a65 222c 2275 7365 724e 616d  y=size","userNam
    0x01f0:  6522 3a22 6d79 7363 6d22 2c22 7573 6572  e":"myscm","user
    0x0200:  4964 223a 3330 3034 2c22 7061 7468 6e61  Id":3004,"pathna
    0x0210:  6d65 223a 222f 6170 692f 7634 2f70 726f  me":"/api/v4/pro
    0x0220:  6a65 6374 732f 3339 3235 352f 6c61 6e67  jects/39255/lang
    0x0230:  7561 6765 7322 2c22 7265 6d6f 7465 4164  uages","remoteAd
    0x0240:  6472 223a 2233 302e 3339 2e32 3232 2e32  dr":"30.39.222.2
    0x0250:  3237 222c 2275 7064 6174 6564 4174 223a  27","updatedAt":
    0x0260:  2232 3032 302d 3032 2d31 3254 3038 3a34  "2020-02-12T08:4
    0x0270:  383a 3433 2e33 3338 227d 0a              8:43.338"}.
</code>```

答: It can be done by client.getLowLevelClient().performRequest(new Request(method, endpoint)), fill INDEX into parameter of method.

Body:
I'm using Java bulk Api,Elasticsearch 6.6.2, and expect to POST bulk request as

POST /<index>/_bulk,

but i got POST /_bulk instead (see packet captured below).

I know these 2 POST methods are the same, but there're a proxy between my app and ES, the path parameter is for the proxy for some reasons(I don't know why).

so, I wonder how to set the path parameter in Java ,so that request can be sent in POST /<index>/_bulk format.

Here's the code

        RestHighLevelClient client;
        /* some client init code ....*/
        ...
        String INDEX = "api_track";
        String DOC_TYPE = "_doc";

        BulkProcessor.Builder builder = BulkProcessor.builder(
                (request, bulkListener) ->
                        client.bulkAsync(request, RequestOptions.DEFAULT, bulkListener),
                listener);
        builder.setBulkActions(500);
        builder.setBulkSize(new ByteSizeValue(1L, ByteSizeUnit.MB));
        builder.setConcurrentRequests(0);
        builder.setFlushInterval(TimeValue.timeValueSeconds(5L));
        builder.setBackoffPolicy(BackoffPolicy
                .constantBackoff(TimeValue.timeValueSeconds(1L), 3));
        builder.setGlobalIndex(INDEX);
        builder.setGlobalType(DOC_TYPE);
        bulkProcessor = builder.build();

        IndexRequest request = new IndexRequest().index(INDEX).type(DOC_TYPE).source(maps);
        bulkProcessor.add(request);

and the packet captured:

    0x0000:  0200 0000 4500 0277 0000 4000 4006 12c9  ....E..w..@.@...
    0x0010:  1e27 dee3 0ba3 1d0b e142 23f0 85d1 ad67  .'.......B#....g
    0x0020:  1540 31d3 8018 0801 3eb0 0000 0101 080a  .@1.....>.......
    0x0030:  1500 c5e6 b6ba 7ff0 504f 5354 202f 5f62  ........POST./_b   <-- POST format here
    0x0040:  756c 6b3f 7469 6d65 6f75 743d 316d 2048  ulk?timeout=1m.H
    0x0050:  5454 502f 312e 310d 0a43 6f6e 7465 6e74  TTP/1.1..Content
    0x0060:  2d4c 656e 6774 683a 2033 3335 0d0a 436f  -Length:.335..Co
    0x0070:  6e74 656e 742d 5479 7065 3a20 6170 706c  ntent-Type:.appl
    0x0080:  6963 6174 696f 6e2f 6a73 6f6e 0d0a 486f  ication/json..Ho
    0x0090:  7374 3a20 7365 6172 6368 2e61 6c69 7061  st:.search.alipa
    0x00a0:  792e 6e65 743a 3932 3030 0d0a 436f 6e6e  y.net:9200..Conn
    0x00b0:  6563 7469 6f6e 3a20 4b65 6570 2d41 6c69  ection:.Keep-Ali
    0x00c0:  7665 0d0a 5573 6572 2d41 6765 6e74 3a20  ve..User-Agent:.
    0x00d0:  4170 6163 6865 2d48 7474 7041 7379 6e63  Apache-HttpAsync
    0x00e0:  436c 6965 6e74 2f34 2e31 2e34 2028 4a61  Client/4.1.4.(Ja
    0x00f0:  7661 2f31 2e38 2e30 5f31 3531 290d 0a41  va/1.8.0_151)..A
    0x0100:  7574 686f 7269 7a61 7469 6f6e 3a20 4261  uthorization:.Ba
    0x0110:  7369 6320 6247 6c75 6132 4d36 527a 4e61  sic.bGlua2M6RzNa
    0x0120:  5954 4e4e 5755 593d 0d0a 0d0a 7b22 696e  YTNNWUY=....{"in
    0x0130:  6465 7822 3a7b 225f 696e 6465 7822 3a22  dex":{"_index":"
    0x0140:  6170 695f 7472 6163 6b22 2c22 5f74 7970  api_track","_typ
    0x0150:  6522 3a22 5f64 6f63 227d 7d0a 7b22 6372  e":"_doc"}}.{"cr
    0x0160:  6561 7465 6441 7422 3a22 3230 3230 2d30  eatedAt":"2020-0
    0x0170:  322d 3132 5430 383a 3438 3a34 332e 3333  2-12T08:48:43.33
    0x0180:  3822 2c22 686f 7374 4164 6472 223a 2231  8","hostAddr":"1
    0x0190:  3237 2e30 2e30 2e31 222c 2274 656e 616e  27.0.0.1","tenan
    0x01a0:  7449 6422 3a6e 756c 6c2c 2273 6572 7665  tId":null,"serve
    0x01b0:  724e 616d 6522 3a6e 756c 6c2c 2270 6172  rName":null,"par
    0x01c0:  616d 7322 3a22 2670 7269 7661 7465 5f74  ams":"&private_t
    0x01d0:  6f6b 656e 3d2a 2a2a 266f 7264 6572 5f62  oken=***&order_b
    0x01e0:  793d 7369 7a65 222c 2275 7365 724e 616d  y=size","userNam
    0x01f0:  6522 3a22 6d79 7363 6d22 2c22 7573 6572  e":"myscm","user
    0x0200:  4964 223a 3330 3034 2c22 7061 7468 6e61  Id":3004,"pathna
    0x0210:  6d65 223a 222f 6170 692f 7634 2f70 726f  me":"/api/v4/pro
    0x0220:  6a65 6374 732f 3339 3235 352f 6c61 6e67  jects/39255/lang
    0x0230:  7561 6765 7322 2c22 7265 6d6f 7465 4164  uages","remoteAd
    0x0240:  6472 223a 2233 302e 3339 2e32 3232 2e32  dr":"30.39.222.2
    0x0250:  3237 222c 2275 7064 6174 6564 4174 223a  27","updatedAt":
    0x0260:  2232 3032 302d 3032 2d31 3254 3038 3a34  "2020-02-12T08:4
    0x0270:  383a 3433 2e33 3338 227d 0a              8:43.338"}.


来源: stackexchange

问:
Graph not showing properly in page in shiny
I am new to shiny and i have the following problem. My plot doesn't show up in the whole page. I searched about the fillPage and fluidPage but i couldn't make any progress.  My code is the following:

```<code>library(shiny)
library(demography)
library(shinythemes)

ui <-fillPage(

titlePanel("Mortality"),

 sidebarLayout(

sidebarPanel(

  selectInput(inputId = "dataset",
              label = "Choose a dataset:",
              choices = c( "Austria","Belgium","Bulgaria","Czech Republic","Denmark","Finland","France","Germany","Greece","Iceland","Italy","Luxembourg","Netherlands","Portugal","Spain","Sweden","Switzerland","U.K","Ukraine"))

),

mainPanel(

  textOutput("caption", container = span),

  verbatimTextOutput("summary"),

  plotOutput('plot')

    )
    )
   )
    server <- function(input, output) {

 Austria=hmd.mx("AUT",, , "AUT")

datasetInput <- reactive({
    switch(input$dataset,
       "Austria"=Austria,
       "Belgium"=Belgium,
       "Bulgaria"=Bulgaria,
       "Czech Republic"=Czech.Republic,
       "Denmark"=Denmark,
       "Finland"=Finland,
       "France"=France,
       "Germany"=Germany,
       "Greece"=Greece,
       "Iceland"=Iceland,
       "Italy"=Italy,
       "Luxembourg"=Luxembourg,
       "Netherlands"=Netherlands,
       "Portugal"=Portugal,
       "Spain"=Spain,
       "Sweden"=Sweden,
       "Switzerland"=Switzerland,
       "U.K"=U.K)
   })

  output$caption <- renderText({
    input$dataset
   })

  output$summary <- renderPrint({
    dataset <- datasetInput()
   summary(dataset)
  })

 output$plot <- renderPlot({
   dataset <- datasetInput()
   plot(dataset)
   })

   }

  shinyApp(ui, server)
</code>```

Here is a screenshot.
Thank you for your time image

PS. In my code i have data from other countries, not only Austria

答:
Try fillPage height

fillPage(plotOutput("plot", height = "100%"))

ContentLicense: CC BY-SA 4.0

Body:
I am new to shiny and i have the following problem. My plot doesn't show up in the whole page. I searched about the fillPage and fluidPage but i couldn't make any progress.  My code is the following:

library(shiny)
library(demography)
library(shinythemes)

ui <-fillPage(

titlePanel("Mortality"),

 sidebarLayout(

sidebarPanel(

  selectInput(inputId = "dataset",
              label = "Choose a dataset:",
              choices = c( "Austria","Belgium","Bulgaria","Czech Republic","Denmark","Finland","France","Germany","Greece","Iceland","Italy","Luxembourg","Netherlands","Portugal","Spain","Sweden","Switzerland","U.K","Ukraine"))

),

mainPanel(

  textOutput("caption", container = span),

  verbatimTextOutput("summary"),

  plotOutput('plot')

    )
    )
   )
    server <- function(input, output) {

 Austria=hmd.mx("AUT",, , "AUT")

datasetInput <- reactive({
    switch(input$dataset,
       "Austria"=Austria,
       "Belgium"=Belgium,
       "Bulgaria"=Bulgaria,
       "Czech Republic"=Czech.Republic,
       "Denmark"=Denmark,
       "Finland"=Finland,
       "France"=France,
       "Germany"=Germany,
       "Greece"=Greece,
       "Iceland"=Iceland,
       "Italy"=Italy,
       "Luxembourg"=Luxembourg,
       "Netherlands"=Netherlands,
       "Portugal"=Portugal,
       "Spain"=Spain,
       "Sweden"=Sweden,
       "Switzerland"=Switzerland,
       "U.K"=U.K)
   })

  output$caption <- renderText({
    input$dataset
   })

  output$summary <- renderPrint({
    dataset <- datasetInput()
   summary(dataset)
  })

 output$plot <- renderPlot({
   dataset <- datasetInput()
   plot(dataset)
   })

   }

  shinyApp(ui, server)

Here is a screenshot.
Thank you for your time image

PS. In my code i have data from other countries, not only Austria


问:
How can I use preg_match in jQuery?
Can I use preg_match to validate phone number in jQuery? Here is my code which does not work:

```<code>if (!preg_match("/^[0-9]{3}-|\s[0-9]{3}-|\s[0-9]{4}$/", phone.val() ))  {
            phone.addClass("needsfilled");
            phone.val(phonerror);
        }
</code>```

HTML
<input id="phone" type="text" value=""  name="phone" />

答:
To use a PHP function, you will have to make an HTTP request to the server (with whatever data you want to test) and then parse the response.

Better to use JavaScript's native regular expression functionality.

Title: How can I use preg_match in jQuery?

Body:
Can I use preg_match to validate phone number in jQuery? Here is my code which does not work:

if (!preg_match("/^[0-9]{3}-|\s[0-9]{3}-|\s[0-9]{4}$/", phone.val() ))  {
            phone.addClass("needsfilled");
            phone.val(phonerror);
        }

HTML
<input id="phone" type="text" value=""  name="phone" />

ContentLicense: CC BY-SA 3.0


问:
How can I make read and write http requests in godot with gdscript?
I want to use a spreadsheet as my database for a game and when I do a POST HTTPRequest I get an error of authentication because I can't (of course) sign in to google in my game. I want to know how to give my script OAuth 2.0 access to my spreadsheet and API.</p>

答:
Everything you need to do to get an access token for the sheets api is explained here:
https://developers.google.com/identity/protocols/OAuth2#basicsteps

I guess you already knew that, but here ...
https://docs.godotengine.org/de/latest/tutorials/networking/http_request_class.html

... is an example how to include headers in your http request in godot.

so in Godot you have to obtain an access token as descriped in the basic steps point 2 and save it. Then you are able to send requests to edit your spreadsheet by adding an Authentication header with the obtained access token to them.


问:
SOLR: Spell check not working with select query
In the SOLR admin, we can see there is a spellcheck option but it is not showing the result.

How this is works with the select query.

If I searched with the spell URL direct, It gives me result as expected

http://localhost:8983/solr/prashant1/spell?q=blakc&spellcheck=on&wt=json

Result

```<code>{
  "responseHeader":{
    "status":0,
    "QTime":8},
  "response":{"numFound":0,"start":0,"docs":[]
  },
  "spellcheck":{
    "suggestions":[
      "blakc",{
        "numFound":10,
        "startOffset":0,
        "endOffset":5,
        "origFreq":0,
        "suggestion":[{
            "word":"black",
            "freq":65146},
          {
            "word":"blanc",
            "freq":151},
          {
            "word":"blake",
            "freq":10},
          {
            "word":"blac",
            "freq":2},
          {
            "word":"block",
            "freq":1863},
          {
            "word":"blanca",
            "freq":32},
          {
            "word":"blank",
            "freq":31},
          {
            "word":"blade",
            "freq":23},
          {
            "word":"blacks",
            "freq":12},
          {
            "word":"blanco",
            "freq":11}]}],
    "correctlySpelled":false,
    "collations":[]}}
</code>```

But I need the same result with the select query which is not working from the SOLR admin.

Solrconfig.xml

```<code><searchComponent name="spellcheck" class="solr.SpellCheckComponent">
    <str name="queryAnalyzerFieldType">text_general</str>
    <!-- Multiple "Spell Checkers" can be declared and used by this
         component
      -->
    <!-- a spellchecker built from a field of the main index -->
    <lst name="spellchecker">
      <str name="name">default</str>
      <str name="field">Name</str>
      <str name="classname">solr.DirectSolrSpellChecker</str>
      <!-- the spellcheck distance measure used, the default is the internal levenshtein -->
      <str name="distanceMeasure">internal</str>
      <!-- minimum accuracy needed to be considered a valid spellcheck suggestion -->
      <float name="accuracy">0.5</float>
      <!-- the maximum #edits we consider when enumerating terms: can be 1 or 2 -->
      <int name="maxEdits">2</int>
      <!-- the minimum shared prefix when enumerating terms -->
      <int name="minPrefix">1</int>
      <!-- maximum number of inspections per result. -->
      <int name="maxInspections">5</int>
      <!-- minimum length of a query term to be considered for correction -->
      <int name="minQueryLength">4</int>
      <!-- maximum threshold of documents a query term can appear to be considered for correction -->
      <float name="maxQueryFrequency">0.01</float>
      <!-- uncomment this to require suggestions to occur in 1% of the documents
        <float name="thresholdTokenFrequency">.01</float>
      -->
    </lst>
</searchComponent>

<requestHandler name="/spell" class="solr.SearchHandler" startup="lazy">
    <lst name="defaults">
      <str name="spellcheck.dictionary">default</str>
      <str name="spellcheck">on</str>
      <str name="spellcheck.extendedResults">true</str>
      <str name="spellcheck.count">10</str>
      <str name="spellcheck.alternativeTermCount">5</str>
      <str name="spellcheck.maxResultsForSuggest">5</str>
      <str name="spellcheck.collate">true</str>
      <str name="spellcheck.collateExtendedResults">true</str>
      <str name="spellcheck.maxCollationTries">10</str>
      <str name="spellcheck.maxCollations">5</str>
    </lst>
    <arr name="last-components">
      <str>spellcheck</str>
    </arr>
</requestHandler>
</code>```

It should work with:

http://localhost:8983/solr/prashant1/select?q=Name%3Ablakc&spellcheck.q=blakc&spellcheck=on

Is there any setting and steps to be done?

答:
Try by adding the spellcheck component to the standard query handler like

```<code><requestHandler name="/select" class="solr.SearchHandler">
    <lst name="defaults">
      <str name="echoParams">explicit</str>
      <int name="rows">10</int>

    <str name="spellcheck">on</str>
      <str name="spellcheck.extendedResults">true</str>
      <str name="spellcheck.count">10</str>
    </lst>
    <arr name="last-components">
      <str>spellcheck</str>
    </arr>
</requestHandler>
</code>```

You can then call it like this:

```<code>http://localhost:8983/solr/select?q=yogik&spellcheck=true
</code>```

Also don't forget to build the spellcheck dictionary before you use it:

```<code>http://localhost:8983/solr/select/?q=*:*&spellcheck=true&spellcheck.build=true
</code>```

Body:
In the SOLR admin, we can see there is a spellcheck option but it is not showing the result.

How this is works with the select query.

If I searched with the spell URL direct, It gives me result as expected

http://localhost:8983/solr/prashant1/spell?q=blakc&spellcheck=on&wt=json

Result

{
  "responseHeader":{
    "status":0,
    "QTime":8},
  "response":{"numFound":0,"start":0,"docs":[]
  },
  "spellcheck":{
    "suggestions":[
      "blakc",{
        "numFound":10,
        "startOffset":0,
        "endOffset":5,
        "origFreq":0,
        "suggestion":[{
            "word":"black",
            "freq":65146},
          {
            "word":"blanc",
            "freq":151},
          {
            "word":"blake",
            "freq":10},
          {
            "word":"blac",
            "freq":2},
          {
            "word":"block",
            "freq":1863},
          {
            "word":"blanca",
            "freq":32},
          {
            "word":"blank",
            "freq":31},
          {
            "word":"blade",
            "freq":23},
          {
            "word":"blacks",
            "freq":12},
          {
            "word":"blanco",
            "freq":11}]}],
    "correctlySpelled":false,
    "collations":[]}}

But I need the same result with the select query which is not working from the SOLR admin.

Solrconfig.xml

<searchComponent name="spellcheck" class="solr.SpellCheckComponent">
    <str name="queryAnalyzerFieldType">text_general</str>

    <lst name="spellchecker">
      <str name="name">default</str>
      <str name="field">Name</str>
      <str name="classname">solr.DirectSolrSpellChecker</str>

      <str name="distanceMeasure">internal</str>

      <float name="accuracy">0.5</float>

      <int name="maxEdits">2</int>

      <int name="minPrefix">1</int>

      <int name="maxInspections">5</int>

      <int name="minQueryLength">4</int>

      <float name="maxQueryFrequency">0.01</float>

    </lst>
</searchComponent>

<requestHandler name="/spell" class="solr.SearchHandler" startup="lazy">
    <lst name="defaults">
      <str name="spellcheck.dictionary">default</str>
      <str name="spellcheck">on</str>
      <str name="spellcheck.extendedResults">true</str>
      <str name="spellcheck.count">10</str>
      <str name="spellcheck.alternativeTermCount">5</str>
      <str name="spellcheck.maxResultsForSuggest">5</str>
      <str name="spellcheck.collate">true</str>
      <str name="spellcheck.collateExtendedResults">true</str>
      <str name="spellcheck.maxCollationTries">10</str>
      <str name="spellcheck.maxCollations">5</str>
    </lst>
    <arr name="last-components">
      <str>spellcheck</str>
    </arr>
</requestHandler>

It should work with:

http://localhost:8983/solr/prashant1/select?q=Name%3Ablakc&spellcheck.q=blakc&spellcheck=on

Is there any setting and steps to be done?

Body:
Try by adding the spellcheck component to the standard query handler like

<requestHandler name="/select" class="solr.SearchHandler">
    <lst name="defaults">
      <str name="echoParams">explicit</str>
      <int name="rows">10</int>

    <str name="spellcheck">on</str>
      <str name="spellcheck.extendedResults">true</str>
      <str name="spellcheck.count">10</str>
    </lst>
    <arr name="last-components">
      <str>spellcheck</str>
    </arr>
</requestHandler>

You can then call it like this:

http://localhost:8983/solr/select?q=yogik&spellcheck=true

Also don't forget to build the spellcheck dictionary before you use it:

http://localhost:8983/solr/select/?q=*:*&spellcheck=true&spellcheck.build=true


问:
C: UTF-8 file imported in UTF-8 program prints in UTF-8 terminal "?" characters that indicate unknown symbols
I have a C program test.elf that should process UTF-8 encoded file and print it inside a terminal on a  UTF-8 system. Now someone gave me a file components.csv which is ISO-8859-1 encoded. And I encountered problems.

My system's encoding can be checked in a terminal and it is indeed UTF-8:

```<code>[ziga@localhost ~]$ echo $LANG
en_US.UTF-8
</code>```

I can also check or guess (!) file's encoding which is one of the ISO-8859-{1,2,3,4,5,6,7,8,9,10,11,13,14,15} (source):

```<code>[ziga@localhost ~]$ file components.csv
components.csv: ISO-8859 text, with very long lines, with CRLF line terminators
</code>```

If I read this file directly using cat and limit output to first couple of lines using head, I see the first unknown character �. This is expected, because system is in UTF-8 that can handle ASCII characters, but not extended ASCII characters (source) where probably � belongs to:

```<code>[ziga@localhost ~]$ cat components.csv | head -n4
id_articolo,codice,descrizione,esistenza,disponibilita,qta_rim_iniziale,qta_caricata,qta_scaricata,qta_ord_clienti,qta_ord_fornitori,val_rim_iniziale,val_caricato,val_scaricato,ultimo_costo,c_scorta_min,c_cod_fornitore,c_des_fornitore,c_prd_qta_avanz,c_prd_qta_wip,prezzo_listino,codice,qta_altri_carichi,qta_altri_scarichi
41,15MQ040N,Diodo schottky 3A 40V SMA,6755,0000,6755,0000,6755,0000,0,0,0,0,0,0,0,0,0,,,0,0,0,NR,0,0
49,24LC256-I/SN,Memoria flash 8 pin SOIC-8 256kbit,22,0000,22,0000,22,0000,0,0,0,0,16,0600,0,0,0,0,57010035,EBV Elektronik,0,0,0,NR,0,0
2156,24LC512-I/SN,"Memoria EEPROM I2C 64kx8bit 2,5�5,5V 400kHz SOIC8",92,0000,92,0000,92,0000,0,0,0,0,50,6000,0,0,0,0,57010274,GSE s.r.l.,0,0,0,NR,0,0
</code>```

Now If I process this file directly with my program, the program will end it's execution at this exact character and this is also expected:

```<code>[ziga@localhost ~]$ ./test.elf components.csv a
―――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――
1:
    Commencing import procedure of file "components.csv" into SQLite database "a".
―――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――
2:
    CSV file "components.csv" found.
―――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――
3:
    Printing inputed file "components.csv":

id_articolo,codice,descrizione,esistenza,disponibilita,qta_rim_iniziale,qta_caricata,qta_scaricata,qta_ord_clienti,qta_ord_fornitori,val_rim_iniziale,val_caricato,val_scaricato,ultimo_costo,c_scorta_min,c_cod_fornitore,c_des_fornitore,c_prd_qta_avanz,c_prd_qta_wip,prezzo_listino,codice,qta_altri_carichi,qta_altri_scarichi
41,15MQ040N,Diodo schottky 3A 40V SMA,6755,0000,6755,0000,6755,0000,0,0,0,0,0,0,0,0,0,,,0,0,0,NR,0,0
49,24LC256-I/SN,Memoria flash 8 pin SOIC-8 256kbit,22,0000,22,0000,22,0000,0,0,0,0,16,0600,0,0,0,0,57010035,EBV Elektronik,0,0,0,NR,0,0
2156,24LC512-I/SN,"Memoria EEPROM I2C 64kx8bit 2,5
</code>```

But now I will convert the file's encoding and create a new file components-utf8.csv in UTF-8 encoding. I tried this procedure multiple times for every ISO-8859-{1,2,3,4,5,6,7,8,9,10,11,13,14,15} encoding and the solution below yields best results:

```<code>iconv -f ISO-8859-1 -t UTF-8 components.csv > components-utf8.csv
</code>```

If I process new file using cat and head, unknown character now renders fine as ÷:

```<code>[ziga@localhost ~]$ cat components-utf8.csv | head -n4
id_articolo,codice,descrizione,esistenza,disponibilita,qta_rim_iniziale,qta_caricata,qta_scaricata,qta_ord_clienti,qta_ord_fornitori,val_rim_iniziale,val_caricato,val_scaricato,ultimo_costo,c_scorta_min,c_cod_fornitore,c_des_fornitore,c_prd_qta_avanz,c_prd_qta_wip,prezzo_listino,codice,qta_altri_carichi,qta_altri_scarichi
41,15MQ040N,Diodo schottky 3A 40V SMA,6755,0000,6755,0000,6755,0000,0,0,0,0,0,0,0,0,0,,,0,0,0,NR,0,0
49,24LC256-I/SN,Memoria flash 8 pin SOIC-8 256kbit,22,0000,22,0000,22,0000,0,0,0,0,16,0600,0,0,0,0,57010035,EBV Elektronik,0,0,0,NR,0,0
2156,24LC512-I/SN,"Memoria EEPROM I2C 64kx8bit 2,5÷5,5V 400kHz SOIC8",92,0000,92,0000,92,0000,0,0,0,0,50,6000,0,0,0,0,57010274,GSE s.r.l.,0,0,0,NR,0,0
</code>```

If I process new file with my program, it executes from the start till the end (here I will just paste first couple of lines), but renders ÷ as ?:

```<code>[ziga@localhost ~]$ ./test.elf components-utf8.csv a
―――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――
1:
    Commencing import procedure of file "components-utf8.csv" into SQLite database "a".
―――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――
2:
    CSV file "components-utf8.csv" found.
―――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――
3:
    Printing inputed file "components-utf8.csv":

id_articolo,codice,descrizione,esistenza,disponibilita,qta_rim_iniziale,qta_caricata,qta_scaricata,qta_ord_clienti,qta_ord_fornitori,val_rim_iniziale,val_caricato,val_scaricato,ultimo_costo,c_scorta_min,c_cod_fornitore,c_des_fornitore,c_prd_qta_avanz,c_prd_qta_wip,prezzo_listino,codice,qta_altri_carichi,qta_altri_scarichi
41,15MQ040N,Diodo schottky 3A 40V SMA,6755,0000,6755,0000,6755,0000,0,0,0,0,0,0,0,0,0,,,0,0,0,NR,0,0
49,24LC256-I/SN,Memoria flash 8 pin SOIC-8 256kbit,22,0000,22,0000,22,0000,0,0,0,0,16,0600,0,0,0,0,57010035,EBV Elektronik,0,0,0,NR,0,0
2156,24LC512-I/SN,"Memoria EEPROM I2C 64kx8bit 2,5?5,5V 400kHz SOIC8",92,0000,92,0000,92,0000,0,0,0,0,50,6000,0,0,0,0,57010274,GSE s.r.l.,0,0,0,NR,0,0
</code>```

This is a mistery to me. Especialy because my program sets it's internal encoding to immitate system's encoding and I also use wide printing functions. Here is the source code of the program:

```<code>// Headers:
#include <locale.h>
#include <wchar.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>

// Function prototypes:
void ruler(void);

// Function definitions:
void ruler(void){
    char* r1 = getenv("COLUMNS");
    int r2;
    if(r1 == NULL){
        r2 = 100;
    }
    else{
        r2 = strtol(r1, NULL, 10);
    }
    int i;
    for(i = 0; i < r2; i++){
        putwchar(L'―');
    }
    putwchar(L'\n');
}

// Entry point:
int main(int argc, char** argv){

    // Setting the user-perfered locale.
    setlocale(LC_ALL, "en_US.UTF-8");

    ruler();

    // Check if exactly two arguments are passed to the binary
    if(argc != 3){
        wprintf(L"USAGE:\n\t%s <CSV file in UTF-8 encoding> <database>\n\nHINT:\n\tUse terminal application \"file\" to guess CSV file's encoding and \"iconv\" to transcode it to UTF-8\n", argv[0]);
        ruler();
        return 1;
    }
    else{
        wprintf(L"1:\n\tCommencing import procedure of file \"%s\" into SQLite database \"%s\".\n", argv[1], argv[2]);
        ruler();
    }

    // Open CSV file
    FILE* csv_file = fopen(argv[1], "r");
    if(csv_file == NULL){
        wprintf(L"2:\n\tCSV file \"%s\" not found.\n", argv[1]);
        ruler();
        return 1;
    }
    else{
        wprintf(L"2:\n\tCSV file \"%s\" found.\n", argv[1]);
        ruler();
    }

    // Print CSV file
    wprintf(L"3:\n\tPrinting inputed file \"%s\":\n\n", argv[1]);
    char c = fgetwc(csv_file);
    while(c != WEOF){
        putwchar(c);
        c = fgetwc(csv_file);
    }
    putwchar(L'\n');

    return 0;

}
</code>```

答:
You need to use the correct type to represent wide characters - char is not sufficient for that.

```<code>char c = fgetwc(csv_file);
</code>```

should be :

```<code>wint_t c = fgetwc(csv_file);
</code>```

as per the fgetwc reference.

For other uses (ie. when not dealing with a return value), there's wchar_t to represent wide characters.

Body:
I have a C program test.elf that should process UTF-8 encoded file and print it inside a terminal on a  UTF-8 system. Now someone gave me a file components.csv which is ISO-8859-1 encoded. And I encountered problems.

My system's encoding can be checked in a terminal and it is indeed UTF-8:

[ziga@localhost ~]$ echo $LANG
en_US.UTF-8

I can also check or guess (!) file's encoding which is one of the ISO-8859-{1,2,3,4,5,6,7,8,9,10,11,13,14,15} (source):

[ziga@localhost ~]$ file components.csv
components.csv: ISO-8859 text, with very long lines, with CRLF line terminators

If I read this file directly using cat and limit output to first couple of lines using head, I see the first unknown character �. This is expected, because system is in UTF-8 that can handle ASCII characters, but not extended ASCII characters (source) where probably � belongs to:

[ziga@localhost ~]$ cat components.csv | head -n4
id_articolo,codice,descrizione,esistenza,disponibilita,qta_rim_iniziale,qta_caricata,qta_scaricata,qta_ord_clienti,qta_ord_fornitori,val_rim_iniziale,val_caricato,val_scaricato,ultimo_costo,c_scorta_min,c_cod_fornitore,c_des_fornitore,c_prd_qta_avanz,c_prd_qta_wip,prezzo_listino,codice,qta_altri_carichi,qta_altri_scarichi
41,15MQ040N,Diodo schottky 3A 40V SMA,6755,0000,6755,0000,6755,0000,0,0,0,0,0,0,0,0,0,,,0,0,0,NR,0,0
49,24LC256-I/SN,Memoria flash 8 pin SOIC-8 256kbit,22,0000,22,0000,22,0000,0,0,0,0,16,0600,0,0,0,0,57010035,EBV Elektronik,0,0,0,NR,0,0
2156,24LC512-I/SN,"Memoria EEPROM I2C 64kx8bit 2,5�5,5V 400kHz SOIC8",92,0000,92,0000,92,0000,0,0,0,0,50,6000,0,0,0,0,57010274,GSE s.r.l.,0,0,0,NR,0,0

Now If I process this file directly with my program, the program will end it's execution at this exact character and this is also expected:

[ziga@localhost ~]$ ./test.elf components.csv a
―――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――
1:
    Commencing import procedure of file "components.csv" into SQLite database "a".
―――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――
2:
    CSV file "components.csv" found.
―――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――
3:
    Printing inputed file "components.csv":

id_articolo,codice,descrizione,esistenza,disponibilita,qta_rim_iniziale,qta_caricata,qta_scaricata,qta_ord_clienti,qta_ord_fornitori,val_rim_iniziale,val_caricato,val_scaricato,ultimo_costo,c_scorta_min,c_cod_fornitore,c_des_fornitore,c_prd_qta_avanz,c_prd_qta_wip,prezzo_listino,codice,qta_altri_carichi,qta_altri_scarichi
41,15MQ040N,Diodo schottky 3A 40V SMA,6755,0000,6755,0000,6755,0000,0,0,0,0,0,0,0,0,0,,,0,0,0,NR,0,0
49,24LC256-I/SN,Memoria flash 8 pin SOIC-8 256kbit,22,0000,22,0000,22,0000,0,0,0,0,16,0600,0,0,0,0,57010035,EBV Elektronik,0,0,0,NR,0,0
2156,24LC512-I/SN,"Memoria EEPROM I2C 64kx8bit 2,5

But now I will convert the file's encoding and create a new file components-utf8.csv in UTF-8 encoding. I tried this procedure multiple times for every ISO-8859-{1,2,3,4,5,6,7,8,9,10,11,13,14,15} encoding and the solution below yields best results:

iconv -f ISO-8859-1 -t UTF-8 components.csv > components-utf8.csv

If I process new file using cat and head, unknown character now renders fine as ÷:

[ziga@localhost ~]$ cat components-utf8.csv | head -n4
id_articolo,codice,descrizione,esistenza,disponibilita,qta_rim_iniziale,qta_caricata,qta_scaricata,qta_ord_clienti,qta_ord_fornitori,val_rim_iniziale,val_caricato,val_scaricato,ultimo_costo,c_scorta_min,c_cod_fornitore,c_des_fornitore,c_prd_qta_avanz,c_prd_qta_wip,prezzo_listino,codice,qta_altri_carichi,qta_altri_scarichi
41,15MQ040N,Diodo schottky 3A 40V SMA,6755,0000,6755,0000,6755,0000,0,0,0,0,0,0,0,0,0,,,0,0,0,NR,0,0
49,24LC256-I/SN,Memoria flash 8 pin SOIC-8 256kbit,22,0000,22,0000,22,0000,0,0,0,0,16,0600,0,0,0,0,57010035,EBV Elektronik,0,0,0,NR,0,0
2156,24LC512-I/SN,"Memoria EEPROM I2C 64kx8bit 2,5÷5,5V 400kHz SOIC8",92,0000,92,0000,92,0000,0,0,0,0,50,6000,0,0,0,0,57010274,GSE s.r.l.,0,0,0,NR,0,0

If I process new file with my program, it executes from the start till the end (here I will just paste first couple of lines), but renders ÷ as ?:

[ziga@localhost ~]$ ./test.elf components-utf8.csv a
―――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――
1:
    Commencing import procedure of file "components-utf8.csv" into SQLite database "a".
―――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――
2:
    CSV file "components-utf8.csv" found.
―――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――
3:
    Printing inputed file "components-utf8.csv":

id_articolo,codice,descrizione,esistenza,disponibilita,qta_rim_iniziale,qta_caricata,qta_scaricata,qta_ord_clienti,qta_ord_fornitori,val_rim_iniziale,val_caricato,val_scaricato,ultimo_costo,c_scorta_min,c_cod_fornitore,c_des_fornitore,c_prd_qta_avanz,c_prd_qta_wip,prezzo_listino,codice,qta_altri_carichi,qta_altri_scarichi
41,15MQ040N,Diodo schottky 3A 40V SMA,6755,0000,6755,0000,6755,0000,0,0,0,0,0,0,0,0,0,,,0,0,0,NR,0,0
49,24LC256-I/SN,Memoria flash 8 pin SOIC-8 256kbit,22,0000,22,0000,22,0000,0,0,0,0,16,0600,0,0,0,0,57010035,EBV Elektronik,0,0,0,NR,0,0
2156,24LC512-I/SN,"Memoria EEPROM I2C 64kx8bit 2,5?5,5V 400kHz SOIC8",92,0000,92,0000,92,0000,0,0,0,0,50,6000,0,0,0,0,57010274,GSE s.r.l.,0,0,0,NR,0,0

This is a mistery to me. Especialy because my program sets it's internal encoding to immitate system's encoding and I also use wide printing functions. Here is the source code of the program:

// Headers:
#include <locale.h>
#include <wchar.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>

// Function prototypes:
void ruler(void);

// Function definitions:
void ruler(void){
    char* r1 = getenv("COLUMNS");
    int r2;
    if(r1 == NULL){
        r2 = 100;
    }
    else{
        r2 = strtol(r1, NULL, 10);
    }
    int i;
    for(i = 0; i < r2; i++){
        putwchar(L'―');
    }
    putwchar(L'\n');
}

// Entry point:
int main(int argc, char** argv){

    // Setting the user-perfered locale.
    setlocale(LC_ALL, "en_US.UTF-8");

    ruler();

    // Check if exactly two arguments are passed to the binary
    if(argc != 3){
        wprintf(L"USAGE:\n\t%s <CSV file in UTF-8 encoding> <database>\n\nHINT:\n\tUse terminal application \"file\" to guess CSV file's encoding and \"iconv\" to transcode it to UTF-8\n", argv[0]);
        ruler();
        return 1;
    }
    else{
        wprintf(L"1:\n\tCommencing import procedure of file \"%s\" into SQLite database \"%s\".\n", argv[1], argv[2]);
        ruler();
    }

    // Open CSV file
    FILE* csv_file = fopen(argv[1], "r");
    if(csv_file == NULL){
        wprintf(L"2:\n\tCSV file \"%s\" not found.\n", argv[1]);
        ruler();
        return 1;
    }
    else{
        wprintf(L"2:\n\tCSV file \"%s\" found.\n", argv[1]);
        ruler();
    }

    // Print CSV file
    wprintf(L"3:\n\tPrinting inputed file \"%s\":\n\n", argv[1]);
    char c = fgetwc(csv_file);
    while(c != WEOF){
        putwchar(c);
        c = fgetwc(csv_file);
    }
    putwchar(L'\n');

    return 0;

}

Body:
You need to use the correct type to represent wide characters - char is not sufficient for that.

char c = fgetwc(csv_file);

should be :

wint_t c = fgetwc(csv_file);

as per the fgetwc reference.

For other uses (ie. when not dealing with a return value), there's wchar_t to represent wide characters.


问:
How to sort a Vector of Vectors?
In Java I am wondering how to sort vectors of vectors on a particular column where one vector is used as a row and one vector is used to hold all the row vectors e.g.

```<code> Vector row = new Vector();
    Vector main = new Vector();

    row.add("Column1");
    row.add("Column2");
    row.add("Column3");

    main.add(row);
</code>```

Then sort the variables in one of the columns e.g. Column2.

Thank you

答:
You could write a Comparator<Vector> that compares two Vector objects based on their second element and use Collections.sort(List,Comparator) with that.

But in the long run you'll be much better off if you get rid of the Vector-in-Vector construct and replace the inner Vector with a custom class that represents the data that you want it to represent. Then you'd write a Comparator<MyClass> which would be much easier to interpret ("oh, this comparator compares based on the first name" instead of "why does this comparator take the element at index 1 and compare that? What does that mean?").

Title: How to sort a Vector of Vectors?

Body:
In Java I am wondering how to sort vectors of vectors on a particular column where one vector is used as a row and one vector is used to hold all the row vectors e.g.

 Vector row = new Vector();
    Vector main = new Vector();

    row.add("Column1");
    row.add("Column2");
    row.add("Column3");

    main.add(row);

Then sort the variables in one of the columns e.g. Column2.

Thank you


问:
How to extract claims from token in Resource Server, in Spring Boot
My authentication server is configured to retrieve check credentials against a table on my database, with a token enhancer which I use to pass additional claims - access control related stuff.

As such, I've written it like this:

```<code>@Configuration
@EnableAuthorizationServer
public class AuthorizationServerConfig extends AuthorizationServerConfigurerAdapter {
    @Value("${security.signing-key}")
    private String signingKey;
    private @Autowired TokenStore tokenStore;
    private @Autowired AuthenticationManager authenticationManager;
    private @Autowired CustomUserDetailsService userDetailsService;

    private @Autowired JwtAccessTokenConverter accessTokenConverter;

    private static final Logger LOGGER = LogManager.getLogger(AuthorizationServerConfig.class);

    @Bean
    @ConfigurationProperties(prefix = "spring.datasource")
    public DataSource oauthDataSource() {
        DataSource ds = null;
        try {
            Context initialContex = new InitialContext();
            ds = (DataSource) (initialContex.lookup("java:/jdbc/oauthdatasource"));
            if (ds != null) {
                ds.getConnection();
            }
        } catch (NamingException ex) {
            LOGGER.error("Naming exception thrown: ", ex);
        } catch (SQLException ex) {
            LOGGER.info("SQL exception thrown: ", ex);
        }
        return ds;
    }

    @Bean
    public JdbcClientDetailsService clientDetailsServices() {
        return new JdbcClientDetailsService(oauthDataSource());
    }

    @Bean
    public TokenStore tokenStore() {
        return new CustomJdbcTokenStore(oauthDataSource());
    }

    @Bean
    public ApprovalStore approvalStore() {
        return new JdbcApprovalStore(oauthDataSource());
    }

    @Bean
    public AuthorizationCodeServices authorizationCodeServices() {
        return new JdbcAuthorizationCodeServices(oauthDataSource());
    }

    @Bean
    public JwtAccessTokenConverter accessTokenConverter() {
        CustomTokenEnhancer converter = new CustomTokenEnhancer();
        converter.setSigningKey(signingKey);
        return converter;
    }

    @Override
    public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
        clients.withClientDetails(clientDetailsServices());
    }

    @Override
    public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
        endpoints.tokenStore(tokenStore)
                .authenticationManager(authenticationManager)
                .accessTokenConverter(accessTokenConverter)
                .userDetailsService(userDetailsService)
                .reuseRefreshTokens(false);
    }
}
</code>```

This works very fine. When I make a call via POSTMAN, I get something like this:

```<code>{
    "access_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhdWQiOlsic2hhcmVwb3J0YWwiXSwiaW5mb19maXJzdCI6IlRoaXMgaXMgdGhlIGZpcnN0IEluZm8iLCJ1c2VyX25hbWUiOiJBdXRoZW50aWNhdGlvbiIsInNjb3BlIjpbInJlYWQiLCJ3cml0ZSIsInRydXN0Il0sImluZm9fc2Vjb25kIjoiVGhpcyBpcyB0aGUgc2Vjb25kIGluZm8iLCJleHAiOjE1ODA3MTMyOTQsImF1dGhvcml0aWVzIjpbIlJPTEVfVVNFUiJdLCJqdGkiOiI1MTg4MGJhZC00MGJiLTQ3ZTItODRjZS1lNDUyNGY1Y2Y3MzciLCJjbGllbnRfaWQiOiJzaGFyZXBvcnRhbC1jbGllbnQifQ.ABmBjwmVDb2acZtGSQrjKcCwfZwhw4R_rpW4y5JA1jY",
    "token_type": "bearer",
    "refresh_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhdWQiOlsic2hhcmVwb3J0YWwiXSwiaW5mb19maXJzdCI6IlRoaXMgaXMgdGhlIGZpcnN0IEluZm8iLCJ1c2VyX25hbWUiOiJBdXRoZW50aWNhdGlvbiIsInNjb3BlIjpbInJlYWQiLCJ3cml0ZSIsInRydXN0Il0sImF0aSI6IjUxODgwYmFkLTQwYmItNDdlMi04NGNlLWU0NTI0ZjVjZjczNyIsImluZm9fc2Vjb25kIjoiVGhpcyBpcyB0aGUgc2Vjb25kIGluZm8iLCJleHAiOjE1ODA3MTM0MzQsImF1dGhvcml0aWVzIjpbIlJPTEVfVVNFUiJdLCJqdGkiOiIyZDYxMDU2ZC01ZDMwLTRhZTQtOWMxZC0zZjliYjRiOWYxOGIiLCJjbGllbnRfaWQiOiJzaGFyZXBvcnRhbC1jbGllbnQifQ.qSLpJm4QxZTIVn1WYWH7EFBS8ryjF1hsD6RSRrEBZd0",
    "expires_in": 359,
    "scope": "read write trust"
}
</code>```

The problem now is my resource server. This is how it used to be before I added a token enhancer to my authentication server:

```<code>@Configuration
@EnableResourceServer
public class ResourceServerConfig extends ResourceServerConfigurerAdapter {
    private @Autowired CustomAuthenticationEntryPoint entryPoint;
    private @Autowired TokenStore tokenStore;
    private static final String RESOURCE_ID = "resourceid";

    private static final Logger LOGGER = LogManager.getLogger(ResourceServerConfig.class);

    @Bean
    @ConfigurationProperties(prefix = "spring.datasource")
    public DataSource oauthDataSource() {
        DataSource ds = null;
        try {
            Context initialContex = new InitialContext();
            ds = (DataSource) (initialContex.lookup("java:/jdbc/oauthdatasource"));
            if (ds != null) {
                ds.getConnection();
            }
        } catch (NamingException ex) {
            LOGGER.error("Naming exception thrown: ", ex);
        } catch (SQLException ex) {
            LOGGER.info("SQL exception thrown: ", ex);
        }
        return ds;
    }

    @Bean
    public TokenStore getTokenStore() {
        return new JdbcTokenStore(oauthDataSource());
    }

    @Override
    public void configure(HttpSecurity http) throws Exception {
        http
                .authorizeRequests()
                .antMatchers(HttpMethod.GET, "/**").access("#oauth2.hasScope('read')")
                .antMatchers(HttpMethod.POST, "/**").access("#oauth2.hasScope('write')")
                .antMatchers(HttpMethod.PATCH, "/**").access("#oauth2.hasScope('write')")
                .antMatchers(HttpMethod.PUT, "/**").access("#oauth2.hasScope('write')")
                .antMatchers(HttpMethod.DELETE, "/**").access("#oauth2.hasScope('write')")
                .and()
                .headers().addHeaderWriter((request, response) -> {
                    response.addHeader("Access-Control-Allow-Origin", "*");
                    response.setHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS, DELETE");
                    response.setHeader("Access-Control-Max-Age", "3600");
                    response.setHeader("Access-Control-Allow-Headers", "x-requested-with, authorization");
                    if (request.getMethod().equals("OPTIONS")) {
                        response.setStatus(HttpServletResponse.SC_OK);
                    }
                })
                .and().exceptionHandling().authenticationEntryPoint(entryPoint);
    }

    @Override
    public void configure(ResourceServerSecurityConfigurer resources) throws Exception {
        resources.resourceId(RESOURCE_ID).tokenStore(tokenStore).authenticationEntryPoint(entryPoint);
    }
}
</code>```

I wish to retrieve the access control information I've placed as additional claims via the authentication server, but I don't know how to go about it.

I saw a couple of examples on the internet, including this: How to extract claims from Spring Security OAuht2 Boot in the Resource Server?, but none of them are working for me. Or maybe I'm missing something.

Please, what do I have to add to make this possible?

答:
I had to use a third-party library to achieve this.

This is the link to the library: https://github.com/auth0/java-jwt

It works really well.

In my resource server, I can get my token value, and then using the java-jwt library, I can extract any claims I've set in my authorization server:

```<code>public Map<String, Claim> getClaims() {
        Map<String, Claim> claims = new HashMap<>();

        String tokenValue = ((OAuth2AuthenticationDetails)((OAuth2Authentication) authenticationFacade.getAuthentication()).getDetails()).getTokenValue();
        try {
            DecodedJWT jwt = JWT.decode(tokenValue);
            claims = jwt.getClaims();
        } catch (JWTDecodeException ex) {
            LOGGER.info("Error decoding token value");
            LOGGER.error("Error decoding token value", ex);
        }

        return claims;
}
</code>```

You should look at the documentation for java-jwt to learn more.

Body:
My authentication server is configured to retrieve check credentials against a table on my database, with a token enhancer which I use to pass additional claims - access control related stuff.

As such, I've written it like this:

@Configuration
@EnableAuthorizationServer
public class AuthorizationServerConfig extends AuthorizationServerConfigurerAdapter {
    @Value("${security.signing-key}")
    private String signingKey;
    private @Autowired TokenStore tokenStore;
    private @Autowired AuthenticationManager authenticationManager;
    private @Autowired CustomUserDetailsService userDetailsService;

    private @Autowired JwtAccessTokenConverter accessTokenConverter;

    private static final Logger LOGGER = LogManager.getLogger(AuthorizationServerConfig.class);

    @Bean
    @ConfigurationProperties(prefix = "spring.datasource")
    public DataSource oauthDataSource() {
        DataSource ds = null;
        try {
            Context initialContex = new InitialContext();
            ds = (DataSource) (initialContex.lookup("java:/jdbc/oauthdatasource"));
            if (ds != null) {
                ds.getConnection();
            }
        } catch (NamingException ex) {
            LOGGER.error("Naming exception thrown: ", ex);
        } catch (SQLException ex) {
            LOGGER.info("SQL exception thrown: ", ex);
        }
        return ds;
    }

    @Bean
    public JdbcClientDetailsService clientDetailsServices() {
        return new JdbcClientDetailsService(oauthDataSource());
    }

    @Bean
    public TokenStore tokenStore() {
        return new CustomJdbcTokenStore(oauthDataSource());
    }

    @Bean
    public ApprovalStore approvalStore() {
        return new JdbcApprovalStore(oauthDataSource());
    }

    @Bean
    public AuthorizationCodeServices authorizationCodeServices() {
        return new JdbcAuthorizationCodeServices(oauthDataSource());
    }

    @Bean
    public JwtAccessTokenConverter accessTokenConverter() {
        CustomTokenEnhancer converter = new CustomTokenEnhancer();
        converter.setSigningKey(signingKey);
        return converter;
    }

    @Override
    public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
        clients.withClientDetails(clientDetailsServices());
    }

    @Override
    public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
        endpoints.tokenStore(tokenStore)
                .authenticationManager(authenticationManager)
                .accessTokenConverter(accessTokenConverter)
                .userDetailsService(userDetailsService)
                .reuseRefreshTokens(false);
    }
}

This works very fine. When I make a call via POSTMAN, I get something like this:

{
    "access_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhdWQiOlsic2hhcmVwb3J0YWwiXSwiaW5mb19maXJzdCI6IlRoaXMgaXMgdGhlIGZpcnN0IEluZm8iLCJ1c2VyX25hbWUiOiJBdXRoZW50aWNhdGlvbiIsInNjb3BlIjpbInJlYWQiLCJ3cml0ZSIsInRydXN0Il0sImluZm9fc2Vjb25kIjoiVGhpcyBpcyB0aGUgc2Vjb25kIGluZm8iLCJleHAiOjE1ODA3MTMyOTQsImF1dGhvcml0aWVzIjpbIlJPTEVfVVNFUiJdLCJqdGkiOiI1MTg4MGJhZC00MGJiLTQ3ZTItODRjZS1lNDUyNGY1Y2Y3MzciLCJjbGllbnRfaWQiOiJzaGFyZXBvcnRhbC1jbGllbnQifQ.ABmBjwmVDb2acZtGSQrjKcCwfZwhw4R_rpW4y5JA1jY",
    "token_type": "bearer",
    "refresh_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhdWQiOlsic2hhcmVwb3J0YWwiXSwiaW5mb19maXJzdCI6IlRoaXMgaXMgdGhlIGZpcnN0IEluZm8iLCJ1c2VyX25hbWUiOiJBdXRoZW50aWNhdGlvbiIsInNjb3BlIjpbInJlYWQiLCJ3cml0ZSIsInRydXN0Il0sImF0aSI6IjUxODgwYmFkLTQwYmItNDdlMi04NGNlLWU0NTI0ZjVjZjczNyIsImluZm9fc2Vjb25kIjoiVGhpcyBpcyB0aGUgc2Vjb25kIGluZm8iLCJleHAiOjE1ODA3MTM0MzQsImF1dGhvcml0aWVzIjpbIlJPTEVfVVNFUiJdLCJqdGkiOiIyZDYxMDU2ZC01ZDMwLTRhZTQtOWMxZC0zZjliYjRiOWYxOGIiLCJjbGllbnRfaWQiOiJzaGFyZXBvcnRhbC1jbGllbnQifQ.qSLpJm4QxZTIVn1WYWH7EFBS8ryjF1hsD6RSRrEBZd0",
    "expires_in": 359,
    "scope": "read write trust"
}

The problem now is my resource server. This is how it used to be before I added a token enhancer to my authentication server:

@Configuration
@EnableResourceServer
public class ResourceServerConfig extends ResourceServerConfigurerAdapter {
    private @Autowired CustomAuthenticationEntryPoint entryPoint;
    private @Autowired TokenStore tokenStore;
    private static final String RESOURCE_ID = "resourceid";

    private static final Logger LOGGER = LogManager.getLogger(ResourceServerConfig.class);

    @Bean
    @ConfigurationProperties(prefix = "spring.datasource")
    public DataSource oauthDataSource() {
        DataSource ds = null;
        try {
            Context initialContex = new InitialContext();
            ds = (DataSource) (initialContex.lookup("java:/jdbc/oauthdatasource"));
            if (ds != null) {
                ds.getConnection();
            }
        } catch (NamingException ex) {
            LOGGER.error("Naming exception thrown: ", ex);
        } catch (SQLException ex) {
            LOGGER.info("SQL exception thrown: ", ex);
        }
        return ds;
    }

    @Bean
    public TokenStore getTokenStore() {
        return new JdbcTokenStore(oauthDataSource());
    }

    @Override
    public void configure(HttpSecurity http) throws Exception {
        http
                .authorizeRequests()
                .antMatchers(HttpMethod.GET, "/**").access("#oauth2.hasScope('read')")
                .antMatchers(HttpMethod.POST, "/**").access("#oauth2.hasScope('write')")
                .antMatchers(HttpMethod.PATCH, "/**").access("#oauth2.hasScope('write')")
                .antMatchers(HttpMethod.PUT, "/**").access("#oauth2.hasScope('write')")
                .antMatchers(HttpMethod.DELETE, "/**").access("#oauth2.hasScope('write')")
                .and()
                .headers().addHeaderWriter((request, response) -> {
                    response.addHeader("Access-Control-Allow-Origin", "*");
                    response.setHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS, DELETE");
                    response.setHeader("Access-Control-Max-Age", "3600");
                    response.setHeader("Access-Control-Allow-Headers", "x-requested-with, authorization");
                    if (request.getMethod().equals("OPTIONS")) {
                        response.setStatus(HttpServletResponse.SC_OK);
                    }
                })
                .and().exceptionHandling().authenticationEntryPoint(entryPoint);
    }

    @Override
    public void configure(ResourceServerSecurityConfigurer resources) throws Exception {
        resources.resourceId(RESOURCE_ID).tokenStore(tokenStore).authenticationEntryPoint(entryPoint);
    }
}

I wish to retrieve the access control information I've placed as additional claims via the authentication server, but I don't know how to go about it.

I saw a couple of examples on the internet, including this: How to extract claims from Spring Security OAuht2 Boot in the Resource Server?, but none of them are working for me. Or maybe I'm missing something.

Please, what do I have to add to make this possible?

Body:
I had to use a third-party library to achieve this.

This is the link to the library: https://github.com/auth0/java-jwt

It works really well.

In my resource server, I can get my token value, and then using the java-jwt library, I can extract any claims I've set in my authorization server:

public Map<String, Claim> getClaims() {
        Map<String, Claim> claims = new HashMap<>();

        String tokenValue = ((OAuth2AuthenticationDetails)((OAuth2Authentication) authenticationFacade.getAuthentication()).getDetails()).getTokenValue();
        try {
            DecodedJWT jwt = JWT.decode(tokenValue);
            claims = jwt.getClaims();
        } catch (JWTDecodeException ex) {
            LOGGER.info("Error decoding token value");
            LOGGER.error("Error decoding token value", ex);
        }

        return claims;
}

You should look at the documentation for java-jwt to learn more.


问:
How to navigate to other screen in flutter web
I have created a simple code practise flutter web.

I have been trying to navigate between two screen in flutter web. But one i click the button in first screen and navigate to second screen, the second screen is show blank with debug flag at the top right. Once i refresh the second screen data is coming.

How to resolve this issue?

Here is the code

```<code>import 'package:temp/providers/Increment_provider.dart';
import 'package:temp/screens/Detail_screen.dart';
import 'package:provider/provider.dart';

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {

  @override
  Widget build(BuildContext context) {
    return ChangeNotifierProvider<IncrementProvider>(
      create: (btx) => IncrementProvider(),
      child: MaterialApp(
        title: 'Flutter Demo',
        theme: ThemeData(

          primarySwatch: Colors.blue,
        ),
        initialRoute: '/',
        routes: {

          DetailScreen.routeName: (ctx) => DetailScreen(),},
        home: MyHomePage(),
      ),
    );
  }
}

class MyHomePage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    final counter = Provider.of<IncrementProvider>(context, listen: false);

    return Scaffold(
      appBar: AppBar(

        title: Text('Main Screen'),
      ),
      body: Center(

        child: Column(

          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            Text(
              'You have pushed the button this many times:',
            ),
            Consumer<IncrementProvider>(builder: (ctx,counter,ch)=>Text(
                '${counter.count}',
                style: Theme.of(context).textTheme.headline4,
              ),

            ),
            FloatingActionButton(
              onPressed: () {
                Navigator.pushNamed(context,DetailScreen.routeName);
              },
              tooltip: 'Press the button',
              child: Icon(Icons.view_agenda),
            ),
          ],
        ),
      ),

      floatingActionButton: FloatingActionButton(
        onPressed: () => counter.incrementor(),
        tooltip: 'Increment',
        child: Icon(Icons.add),
      ),
    );
  }
}

import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'package:temp/providers/Increment_provider.dart';

class DetailScreen extends StatelessWidget {
  static const routeName='/Detail_screen';
  @override
  Widget build(BuildContext context) {
    final counter=Provider.of<IncrementProvider>(context);
    return Scaffold(

      body: Center(child:Column(
        mainAxisAlignment: MainAxisAlignment.center,
        children: <Widget>[
          Text('The incremented value is ${counter.count}'),

        ],

      ),),

    );

  }

}

import 'package:flutter/material.dart';

class IncrementProvider with ChangeNotifier{
 int _count=0;

int get count=> _count;

void incrementor (){
  _count+=1;

  notifyListeners();
}
}
</code>```

答:
I have removed the provider from the code and used argument to pass the data between the screens.

```<code>import 'package:flutter/material.dart';
import 'package:temp/screens/Detail_screen.dart';

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {

  @override
  Widget build(BuildContext context) {
    return  MaterialApp(
        title: 'Flutter Demo',
        theme: ThemeData(

          primarySwatch: Colors.blue,
        ),
        initialRoute: '/',
        routes: {

          DetailScreen.routeName: (ctx) => DetailScreen(),},
        home: MyHomePage(),
      );
  }
}

class MyHomePage extends StatefulWidget {
  @override
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
    int count=0;

void increment(){
  setState(() {
    count+=1;
    print(count);
  });
}
  @override
  Widget build(BuildContext context) {

    return Scaffold(
      appBar: AppBar(

        title: Text('Main Screen'),
      ),
      body: Center(

        child: Column(

          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            Text(
              'You have pushed the button this many times:',
            ),
    Text(
                '$count',
                style: Theme.of(context).textTheme.headline4,
              ),

            FloatingActionButton(
              onPressed: () {
                Navigator.of(context).pushNamed(DetailScreen.routeName,arguments: count);
              },
              tooltip: 'Press the button',
              child: Icon(Icons.view_agenda),
            ),
          ],
        ),
      ),

      floatingActionButton: FloatingActionButton(
        onPressed: increment,
        tooltip: 'Increment',
        child: Icon(Icons.add),
      ),
    );
  }
}

import 'package:flutter/material.dart';

class DetailScreen extends StatelessWidget {
  static const routeName='/Detail_screen';
  @override
  Widget build(BuildContext context) {
    final count=ModalRoute.of(context).settings.arguments as int;
    return Scaffold(

      body: Center(child:Text('The incremented value is $count',style: TextStyle(color: Colors.black),),),

    );

  }

}
</code>```

P.S: I am testing this code in Chrome Browser where this issue is observed. I have not tested in any emulators.

Please run the code in the chrome browser.

Body:
I have created a simple code practise flutter web.

I have been trying to navigate between two screen in flutter web. But one i click the button in first screen and navigate to second screen, the second screen is show blank with debug flag at the top right. Once i refresh the second screen data is coming.

How to resolve this issue?

Here is the code

import 'package:temp/providers/Increment_provider.dart';
import 'package:temp/screens/Detail_screen.dart';
import 'package:provider/provider.dart';

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {

  @override
  Widget build(BuildContext context) {
    return ChangeNotifierProvider<IncrementProvider>(
      create: (btx) => IncrementProvider(),
      child: MaterialApp(
        title: 'Flutter Demo',
        theme: ThemeData(

          primarySwatch: Colors.blue,
        ),
        initialRoute: '/',
        routes: {

          DetailScreen.routeName: (ctx) => DetailScreen(),},
        home: MyHomePage(),
      ),
    );
  }
}

class MyHomePage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    final counter = Provider.of<IncrementProvider>(context, listen: false);

    return Scaffold(
      appBar: AppBar(

        title: Text('Main Screen'),
      ),
      body: Center(

        child: Column(

          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            Text(
              'You have pushed the button this many times:',
            ),
            Consumer<IncrementProvider>(builder: (ctx,counter,ch)=>Text(
                '${counter.count}',
                style: Theme.of(context).textTheme.headline4,
              ),

            ),
            FloatingActionButton(
              onPressed: () {
                Navigator.pushNamed(context,DetailScreen.routeName);
              },
              tooltip: 'Press the button',
              child: Icon(Icons.view_agenda),
            ),
          ],
        ),
      ),

      floatingActionButton: FloatingActionButton(
        onPressed: () => counter.incrementor(),
        tooltip: 'Increment',
        child: Icon(Icons.add),
      ),
    );
  }
}

import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'package:temp/providers/Increment_provider.dart';

class DetailScreen extends StatelessWidget {
  static const routeName='/Detail_screen';
  @override
  Widget build(BuildContext context) {
    final counter=Provider.of<IncrementProvider>(context);
    return Scaffold(

      body: Center(child:Column(
        mainAxisAlignment: MainAxisAlignment.center,
        children: <Widget>[
          Text('The incremented value is ${counter.count}'),

        ],

      ),),

    );

  }

}

import 'package:flutter/material.dart';

class IncrementProvider with ChangeNotifier{
 int _count=0;

int get count=> _count;

void incrementor (){
  _count+=1;

  notifyListeners();
}
}

Body:
I have removed the provider from the code and used argument to pass the data between the screens.

import 'package:flutter/material.dart';
import 'package:temp/screens/Detail_screen.dart';

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {

  @override
  Widget build(BuildContext context) {
    return  MaterialApp(
        title: 'Flutter Demo',
        theme: ThemeData(

          primarySwatch: Colors.blue,
        ),
        initialRoute: '/',
        routes: {

          DetailScreen.routeName: (ctx) => DetailScreen(),},
        home: MyHomePage(),
      );
  }
}

class MyHomePage extends StatefulWidget {
  @override
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
    int count=0;

void increment(){
  setState(() {
    count+=1;
    print(count);
  });
}
  @override
  Widget build(BuildContext context) {

    return Scaffold(
      appBar: AppBar(

        title: Text('Main Screen'),
      ),
      body: Center(

        child: Column(

          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            Text(
              'You have pushed the button this many times:',
            ),
    Text(
                '$count',
                style: Theme.of(context).textTheme.headline4,
              ),

            FloatingActionButton(
              onPressed: () {
                Navigator.of(context).pushNamed(DetailScreen.routeName,arguments: count);
              },
              tooltip: 'Press the button',
              child: Icon(Icons.view_agenda),
            ),
          ],
        ),
      ),

      floatingActionButton: FloatingActionButton(
        onPressed: increment,
        tooltip: 'Increment',
        child: Icon(Icons.add),
      ),
    );
  }
}

import 'package:flutter/material.dart';

class DetailScreen extends StatelessWidget {
  static const routeName='/Detail_screen';
  @override
  Widget build(BuildContext context) {
    final count=ModalRoute.of(context).settings.arguments as int;
    return Scaffold(

      body: Center(child:Text('The incremented value is $count',style: TextStyle(color: Colors.black),),),

    );

  }

}

P.S: I am testing this code in Chrome Browser where this issue is observed. I have not tested in any emulators.

Please run the code in the chrome browser.


问:
Android / MySQL: Populate Spinner from database with Initial Set Text "Please Select"
I want to ask regarding my codes. I successfully create a spinner that lists data from the database.

In my case, this spinner will populate data from column "fac_name" at table "factory". Now, at initial list of the spinner, I want to display a text "Please Select" and below the text will display the populate data from database. Below is my code.

Java

```<code>public static final String TAG_FAC_NAME = "fac_name";

public static final String JSON_ARRAY = "result";
private JSONArray result;
private ArrayList<String> factoryList;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_add_task);

    factoryList = new ArrayList<>();
    spFactory = findViewById(R.id.spFactory);
    spFactory.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
        @Override
        public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {

        }

        @Override
        public void onNothingSelected(AdapterView<?> parent) {

        }
    });

    getData();

}

private void getData(){
    StringRequest stringRequest = new StringRequest(URLs.URL_SPINNER_FACTORY,
            new Response.Listener<String>() {
                @Override
                public void onResponse(String response) {

                    JSONObject j = null;

                    try {
                        j = new JSONObject(response);

                        result = j.getJSONArray(JSON_ARRAY);

                        getFactory(result);
                    } catch (JSONException e) {
                        e.printStackTrace();
                    }
                }
            },
            new Response.ErrorListener() {
                @Override
                public void onErrorResponse(VolleyError error) {

                }
            });

    RequestQueue requestQueue = Volley.newRequestQueue(this);
    requestQueue.add(stringRequest);
}

private void getFactory(JSONArray j){
    for(int i=0;i<j.length();i++){
        try {
            JSONObject json = j.getJSONObject(i);

            factoryList.add(json.getString(TAG_FAC_NAME));
        } catch (JSONException e) {
            e.printStackTrace();
        }
    }

    spFactory.setAdapter(new ArrayAdapter<String>(AddTask.this, android.R.layout.simple_spinner_dropdown_item, factoryList));
}
</code>```

URL_SPINNER_FACTORY (spinner_factory.php)

```<code><?php

    require_once "../config/configPDO.php";

    $query = $conn->prepare("SELECT * FROM ot_factory ORDER BY fac_id ASC");
    $query->execute();

    $factoryList = array();

    while ($row = $query->fetch(PDO::FETCH_ASSOC)) {
        array_push($factoryList,array(

            'fac_name'=>$row['fac_name'],

            )
        );
    }

    echo json_encode(array('result'=>$factoryList));

?>
</code>```

Can Nyone help me on this? Thank you..

答:
don't worry,

1)you can programmatically set prompt by .setPrompt("Select an item"); just before setting spinner adpter
2)or you can use custom spinner view Don't use a spinner. Instead, use a button and style with the title to look like a spinner (will have to find how I did this). When the user clicks the button, open a "select one" dialog and style it to look like a spinner's dialog. I'll try to put a code sample up shortly.

Body:
I want to ask regarding my codes. I successfully create a spinner that lists data from the database.

In my case, this spinner will populate data from column "fac_name" at table "factory". Now, at initial list of the spinner, I want to display a text "Please Select" and below the text will display the populate data from database. Below is my code.

Java

public static final String TAG_FAC_NAME = "fac_name";

public static final String JSON_ARRAY = "result";
private JSONArray result;
private ArrayList<String> factoryList;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_add_task);

    factoryList = new ArrayList<>();
    spFactory = findViewById(R.id.spFactory);
    spFactory.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
        @Override
        public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {

        }

        @Override
        public void onNothingSelected(AdapterView<?> parent) {

        }
    });

    getData();

}

private void getData(){
    StringRequest stringRequest = new StringRequest(URLs.URL_SPINNER_FACTORY,
            new Response.Listener<String>() {
                @Override
                public void onResponse(String response) {

                    JSONObject j = null;

                    try {
                        j = new JSONObject(response);

                        result = j.getJSONArray(JSON_ARRAY);

                        getFactory(result);
                    } catch (JSONException e) {
                        e.printStackTrace();
                    }
                }
            },
            new Response.ErrorListener() {
                @Override
                public void onErrorResponse(VolleyError error) {

                }
            });

    RequestQueue requestQueue = Volley.newRequestQueue(this);
    requestQueue.add(stringRequest);
}

private void getFactory(JSONArray j){
    for(int i=0;i<j.length();i++){
        try {
            JSONObject json = j.getJSONObject(i);

            factoryList.add(json.getString(TAG_FAC_NAME));
        } catch (JSONException e) {
            e.printStackTrace();
        }
    }

    spFactory.setAdapter(new ArrayAdapter<String>(AddTask.this, android.R.layout.simple_spinner_dropdown_item, factoryList));
}

URL_SPINNER_FACTORY (spinner_factory.php)

<?php

    require_once "../config/configPDO.php";

    $query = $conn->prepare("SELECT * FROM ot_factory ORDER BY fac_id ASC");
    $query->execute();

    $factoryList = array();

    while ($row = $query->fetch(PDO::FETCH_ASSOC)) {
        array_push($factoryList,array(

            'fac_name'=>$row['fac_name'],

            )
        );
    }

    echo json_encode(array('result'=>$factoryList));

?>

Can Nyone help me on this? Thank you..