问:
How can make other button disable when one is clicked android studio?
I have a scenario where I have 5 ImageView and when one ImageView is clicked i want to set other 4 ImageView as Disabled. Please help to get logic for that.
My Logic for this : when 1 image is click set other 4 imageView as disable but imageView.setClickable(false) is not working.

This Attached Image is a dialog box that appears when users wants to edit something from recycler view. Recycler view contains data like : "Amount", "Item name", "Price", "Expense Type" and expense type image is set to On corresponding to "Expense Type".

I am stuck in this moment. Please help me out to solve this.

I have attached my scenario images Please check it out.

Here's my code for this

```<code>public class MyAdapter extends FirebaseRecyclerAdapter<ExpenseModel, MyAdapter.MyViewHolder> {
    Context context;
    private int lastPosition = -1;
    private String whichCategorySelected = "";
    private int calImgClick = 0;
    private int groceryClick = 0;
    private int bikeClick = 0;
    private int rentClick = 0;
    private int foodsClick = 0;
    private int beerClick = 0;

    public MyAdapter(@NonNull FirebaseRecyclerOptions<ExpenseModel> options, Context context) {
        super(options);
        this.context = context;
    }

    @SuppressLint("SetTextI18n")
    @Override
    protected void onBindViewHolder(@NonNull MyViewHolder holder, @SuppressLint("RecyclerView") int position, @NonNull ExpenseModel model) {
        holder.expenseItem.setText(model.getDescription());
        holder.expenseAmount.setText("Rs. " + model.getAmount());
        holder.expenseDate.setText(model.getTime());
        String expType = model.getExType();
        switch (expType) {
            case "Beer":
                holder.category.setBackgroundResource(R.drawable.beer);
                break;
            case "Grocery":
                holder.category.setBackgroundResource(R.drawable.grocery);
                break;
            case "Bike":
                holder.category.setBackgroundResource(R.drawable.bike);
                break;
            case "Rent":
                holder.category.setBackgroundResource(R.drawable.rent);
                break;
            default:
                holder.category.setBackgroundResource(R.drawable.fd);
                break;
        }

        holder.itemView.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                showPopMenuOnItemClicked(view, holder.getLayoutPosition(), model.getDescription(), model.getAmount(), model.getTime(), model.getExType());
            }
        });

    }

    private void showPopMenuOnItemClicked(View v, int pos, String getExpTitle, String getExpAmt, String getDate, String whichCatSelected) {
        PopupMenu popupMenu = new PopupMenu(context, v);
        popupMenu.getMenu().add("Edit");
        popupMenu.getMenu().add("Delete");
        popupMenu.getMenu().add("Delete All");
        popupMenu.setOnMenuItemClickListener(new PopupMenu.OnMenuItemClickListener() {
            @Override
            public boolean onMenuItemClick(MenuItem menuItem) {
                if (menuItem.getTitle().equals("Edit")) {
                    showUpdateDialogBox(v, getExpTitle, getExpAmt, getDate, whichCatSelected);
                } else if (menuItem.getTitle().equals("Delete")) {
                    FirebaseReference.expenseReference(context)
                            .child(String.valueOf(getRef(pos).getKey()))
                            .removeValue()
                            .addOnCompleteListener(new OnCompleteListener<Void>() {
                                @Override
                                public void onComplete(@NonNull Task<Void> task) {
                                    if (task.isSuccessful()) {
                                        Toast.makeText(context, "Deleted", Toast.LENGTH_SHORT).show();
                                    }
                                }
                            });
                } else {
                    Toast.makeText(context.getApplicationContext(), "Delete everything", Toast.LENGTH_SHORT).show();
                }
                return true;
            }
        });
        popupMenu.show();
    }

    @SuppressLint("ClickableViewAccessibility")
    private void showUpdateDialogBox(View v, String getExpTitle, String getExpAmt, String getDate, String whichCatSelected) {
        DialogPlus dialog = DialogPlus.newDialog(context)
                .setContentHolder(new ViewHolder(R.layout.update_expense_layout))
                .setExpanded(false)
                .setOnDismissListener(new OnDismissListener() {
                    @Override
                    public void onDismiss(DialogPlus dialog) {
                        onDismissSetClickCountToZero();
                        Utility.hideKeyboard(context, v);
                    }
                })
                .create();

        View myView = dialog.getHolderView();
        TextView update_expense_date = myView.findViewById(R.id.update_expense_date);
        EditText update_expense_title = myView.findViewById(R.id.update_expense_title);
        EditText update_expense_amount = myView.findViewById(R.id.update_expense_amount);
        ImageView update_calendarImg = myView.findViewById(R.id.update_calendar);
        Button update_button = myView.findViewById(R.id.update_btn);
        LinearLayout linearLayout = myView.findViewById(R.id.update_linearCalenderLayout);
        linearLayout.setVisibility(View.GONE);
        CalendarView calendarView = myView.findViewById(R.id.update_calenderView);
        LinearLayout categoryLayout = myView.findViewById(R.id.update_categoryIconsLayout);
        TextView categoryTextView = myView.findViewById(R.id.update_selectCategory_heading);

        update_expense_title.setText(getExpTitle);
        update_expense_amount.setText(getExpAmt);
        update_expense_date.setText(getDate);

        ImageView beer = myView.findViewById(R.id.update_beer);
        ImageView bike = myView.findViewById(R.id.update_bike);
        ImageView grocery = myView.findViewById(R.id.update_grocery);
        ImageView foods = myView.findViewById(R.id.update_foods);
        ImageView rent = myView.findViewById(R.id.update_rent);

        TextView desc_grocery = myView.findViewById(R.id.update_desc_grocery);
        TextView desc_bike = myView.findViewById(R.id.update_desc_bike);
        TextView desc_beer = myView.findViewById(R.id.update_desc_beer);
        TextView desc_foods = myView.findViewById(R.id.update_desc_foods);
        TextView desc_rent = myView.findViewById(R.id.update_desc_rent);

        setIconVisible(whichCatSelected, bike, grocery, foods, beer, rent,
                desc_bike, desc_grocery, desc_foods, desc_beer, desc_rent);
        setWhichCategorySelected(whichCatSelected);

        Toast.makeText(context, "Default select = " + getWhichCategorySelected() + "  click = " + rentClick, Toast.LENGTH_SHORT).show();
        update_calendarImg.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                calImgClick++;
                if (calImgClick >= 2) {
                    linearLayout.setVisibility(View.GONE);
                    categoryLayout.setVisibility(View.VISIBLE);
                    categoryTextView.setVisibility(View.VISIBLE);
                    calImgClick = 0;
                } else {
                    linearLayout.setVisibility(View.VISIBLE);
                    categoryLayout.setVisibility(View.GONE);
                    categoryTextView.setVisibility(View.GONE);
                }

            }
        });
        rent.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                if (getWhichCategorySelected().equals("") || getWhichCategorySelected().equals("Rent")){
                    rentClick ++;
                    if (rentClick >= 2) {
                        setWhichCategorySelected("");
                        rent.setBackgroundResource(R.drawable.rent_off);
                        desc_rent.setVisibility(View.GONE);
                        grocery.setClickable(true);
                        bike.setClickable(true);
                        foods.setClickable(true);
                        beer.setClickable(true);
                        rentClick = 0;
                    } else {
                        setWhichCategorySelected("Rent");
                        rent.setBackgroundResource(R.drawable.rent);
                        desc_rent.setVisibility(View.VISIBLE);
                        grocery.setClickable(false);
                        bike.setClickable(false);
                        foods.setClickable(false);
                        beer.setClickable(false);
                    }
                }else {
                    Toast.makeText(context, "Category is selected " + getWhichCategorySelected(), Toast.LENGTH_SHORT).show();

                }
                Toast.makeText(context, "whichCategorySelected = " + getWhichCategorySelected(), Toast.LENGTH_SHORT).show();

            }
        });

        grocery.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                if (getWhichCategorySelected().equals("") || getWhichCategorySelected().equals("Grocery")){
                    groceryClick ++;
                    if (groceryClick >= 2) {
                        setWhichCategorySelected("");
                        grocery.setBackgroundResource(R.drawable.grocery_off);
                        desc_grocery.setVisibility(View.GONE);
                        rent.setClickable(true);
                        bike.setClickable(true);
                        foods.setClickable(true);
                        beer.setClickable(true);
                        rentClick = 0;
                    } else {
                        setWhichCategorySelected("Grocery");
                        grocery.setBackgroundResource(R.drawable.grocery);
                        desc_grocery.setVisibility(View.VISIBLE);
                        rent.setClickable(false);
                        bike.setClickable(false);
                        foods.setClickable(false);
                        beer.setClickable(false);
                    }
                }else {
                    Toast.makeText(context, "Category is selected " + getWhichCategorySelected(), Toast.LENGTH_SHORT).show();
                }

                Toast.makeText(context, "whichCategorySelected = " + getWhichCategorySelected(), Toast.LENGTH_SHORT).show();

            }
        });

        update_button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                updateChildren(update_expense_amount, update_expense_title, update_expense_date, whichCatSelected);
            }
        });
        dialog.show();
    }

    @NonNull
    @Override
    public MyViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
        View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_view, parent, false);
        return new MyViewHolder(v);
    }

    public static class MyViewHolder extends RecyclerView.ViewHolder {
        TextView expenseItem, expenseAmount, expenseDate;
        ImageView category;

        public MyViewHolder(@NonNull View itemView) {
            super(itemView);
            expenseItem = itemView.findViewById(R.id.recyclerItemView);
            expenseAmount = itemView.findViewById(R.id.recyclerAmountView);
            expenseDate = itemView.findViewById(R.id.recyclerDateView);
            category = itemView.findViewById(R.id.recyclerCategory);
        }
    }
</code>```

Body:
I have a scenario where I have 5 ImageView and when one ImageView is clicked i want to set other 4 ImageView as Disabled. Please help to get logic for that.
My Logic for this : when 1 image is click set other 4 imageView as disable but imageView.setClickable(false) is not working.

This Attached Image is a dialog box that appears when users wants to edit something from recycler view. Recycler view contains data like : "Amount", "Item name", "Price", "Expense Type" and expense type image is set to On corresponding to "Expense Type".

I am stuck in this moment. Please help me out to solve this.

I have attached my scenario images Please check it out.

Here's my code for this

public class MyAdapter extends FirebaseRecyclerAdapter<ExpenseModel, MyAdapter.MyViewHolder> {
    Context context;
    private int lastPosition = -1;
    private String whichCategorySelected = "";
    private int calImgClick = 0;
    private int groceryClick = 0;
    private int bikeClick = 0;
    private int rentClick = 0;
    private int foodsClick = 0;
    private int beerClick = 0;

    public MyAdapter(@NonNull FirebaseRecyclerOptions<ExpenseModel> options, Context context) {
        super(options);
        this.context = context;
    }

    @SuppressLint("SetTextI18n")
    @Override
    protected void onBindViewHolder(@NonNull MyViewHolder holder, @SuppressLint("RecyclerView") int position, @NonNull ExpenseModel model) {
        holder.expenseItem.setText(model.getDescription());
        holder.expenseAmount.setText("Rs. " + model.getAmount());
        holder.expenseDate.setText(model.getTime());
        String expType = model.getExType();
        switch (expType) {
            case "Beer":
                holder.category.setBackgroundResource(R.drawable.beer);
                break;
            case "Grocery":
                holder.category.setBackgroundResource(R.drawable.grocery);
                break;
            case "Bike":
                holder.category.setBackgroundResource(R.drawable.bike);
                break;
            case "Rent":
                holder.category.setBackgroundResource(R.drawable.rent);
                break;
            default:
                holder.category.setBackgroundResource(R.drawable.fd);
                break;
        }

        holder.itemView.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                showPopMenuOnItemClicked(view, holder.getLayoutPosition(), model.getDescription(), model.getAmount(), model.getTime(), model.getExType());
            }
        });

    }

    private void showPopMenuOnItemClicked(View v, int pos, String getExpTitle, String getExpAmt, String getDate, String whichCatSelected) {
        PopupMenu popupMenu = new PopupMenu(context, v);
        popupMenu.getMenu().add("Edit");
        popupMenu.getMenu().add("Delete");
        popupMenu.getMenu().add("Delete All");
        popupMenu.setOnMenuItemClickListener(new PopupMenu.OnMenuItemClickListener() {
            @Override
            public boolean onMenuItemClick(MenuItem menuItem) {
                if (menuItem.getTitle().equals("Edit")) {
                    showUpdateDialogBox(v, getExpTitle, getExpAmt, getDate, whichCatSelected);
                } else if (menuItem.getTitle().equals("Delete")) {
                    FirebaseReference.expenseReference(context)
                            .child(String.valueOf(getRef(pos).getKey()))
                            .removeValue()
                            .addOnCompleteListener(new OnCompleteListener<Void>() {
                                @Override
                                public void onComplete(@NonNull Task<Void> task) {
                                    if (task.isSuccessful()) {
                                        Toast.makeText(context, "Deleted", Toast.LENGTH_SHORT).show();
                                    }
                                }
                            });
                } else {
                    Toast.makeText(context.getApplicationContext(), "Delete everything", Toast.LENGTH_SHORT).show();
                }
                return true;
            }
        });
        popupMenu.show();
    }

    @SuppressLint("ClickableViewAccessibility")
    private void showUpdateDialogBox(View v, String getExpTitle, String getExpAmt, String getDate, String whichCatSelected) {
        DialogPlus dialog = DialogPlus.newDialog(context)
                .setContentHolder(new ViewHolder(R.layout.update_expense_layout))
                .setExpanded(false)
                .setOnDismissListener(new OnDismissListener() {
                    @Override
                    public void onDismiss(DialogPlus dialog) {
                        onDismissSetClickCountToZero();
                        Utility.hideKeyboard(context, v);
                    }
                })
                .create();

        View myView = dialog.getHolderView();
        TextView update_expense_date = myView.findViewById(R.id.update_expense_date);
        EditText update_expense_title = myView.findViewById(R.id.update_expense_title);
        EditText update_expense_amount = myView.findViewById(R.id.update_expense_amount);
        ImageView update_calendarImg = myView.findViewById(R.id.update_calendar);
        Button update_button = myView.findViewById(R.id.update_btn);
        LinearLayout linearLayout = myView.findViewById(R.id.update_linearCalenderLayout);
        linearLayout.setVisibility(View.GONE);
        CalendarView calendarView = myView.findViewById(R.id.update_calenderView);
        LinearLayout categoryLayout = myView.findViewById(R.id.update_categoryIconsLayout);
        TextView categoryTextView = myView.findViewById(R.id.update_selectCategory_heading);

        update_expense_title.setText(getExpTitle);
        update_expense_amount.setText(getExpAmt);
        update_expense_date.setText(getDate);

        ImageView beer = myView.findViewById(R.id.update_beer);
        ImageView bike = myView.findViewById(R.id.update_bike);
        ImageView grocery = myView.findViewById(R.id.update_grocery);
        ImageView foods = myView.findViewById(R.id.update_foods);
        ImageView rent = myView.findViewById(R.id.update_rent);

        TextView desc_grocery = myView.findViewById(R.id.update_desc_grocery);
        TextView desc_bike = myView.findViewById(R.id.update_desc_bike);
        TextView desc_beer = myView.findViewById(R.id.update_desc_beer);
        TextView desc_foods = myView.findViewById(R.id.update_desc_foods);
        TextView desc_rent = myView.findViewById(R.id.update_desc_rent);

        setIconVisible(whichCatSelected, bike, grocery, foods, beer, rent,
                desc_bike, desc_grocery, desc_foods, desc_beer, desc_rent);
        setWhichCategorySelected(whichCatSelected);

        Toast.makeText(context, "Default select = " + getWhichCategorySelected() + "  click = " + rentClick, Toast.LENGTH_SHORT).show();
        update_calendarImg.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                calImgClick++;
                if (calImgClick >= 2) {
                    linearLayout.setVisibility(View.GONE);
                    categoryLayout.setVisibility(View.VISIBLE);
                    categoryTextView.setVisibility(View.VISIBLE);
                    calImgClick = 0;
                } else {
                    linearLayout.setVisibility(View.VISIBLE);
                    categoryLayout.setVisibility(View.GONE);
                    categoryTextView.setVisibility(View.GONE);
                }

            }
        });
        rent.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                if (getWhichCategorySelected().equals("") || getWhichCategorySelected().equals("Rent")){
                    rentClick ++;
                    if (rentClick >= 2) {
                        setWhichCategorySelected("");
                        rent.setBackgroundResource(R.drawable.rent_off);
                        desc_rent.setVisibility(View.GONE);
                        grocery.setClickable(true);
                        bike.setClickable(true);
                        foods.setClickable(true);
                        beer.setClickable(true);
                        rentClick = 0;
                    } else {
                        setWhichCategorySelected("Rent");
                        rent.setBackgroundResource(R.drawable.rent);
                        desc_rent.setVisibility(View.VISIBLE);
                        grocery.setClickable(false);
                        bike.setClickable(false);
                        foods.setClickable(false);
                        beer.setClickable(false);
                    }
                }else {
                    Toast.makeText(context, "Category is selected " + getWhichCategorySelected(), Toast.LENGTH_SHORT).show();

                }
                Toast.makeText(context, "whichCategorySelected = " + getWhichCategorySelected(), Toast.LENGTH_SHORT).show();

            }
        });

        grocery.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                if (getWhichCategorySelected().equals("") || getWhichCategorySelected().equals("Grocery")){
                    groceryClick ++;
                    if (groceryClick >= 2) {
                        setWhichCategorySelected("");
                        grocery.setBackgroundResource(R.drawable.grocery_off);
                        desc_grocery.setVisibility(View.GONE);
                        rent.setClickable(true);
                        bike.setClickable(true);
                        foods.setClickable(true);
                        beer.setClickable(true);
                        rentClick = 0;
                    } else {
                        setWhichCategorySelected("Grocery");
                        grocery.setBackgroundResource(R.drawable.grocery);
                        desc_grocery.setVisibility(View.VISIBLE);
                        rent.setClickable(false);
                        bike.setClickable(false);
                        foods.setClickable(false);
                        beer.setClickable(false);
                    }
                }else {
                    Toast.makeText(context, "Category is selected " + getWhichCategorySelected(), Toast.LENGTH_SHORT).show();
                }

                Toast.makeText(context, "whichCategorySelected = " + getWhichCategorySelected(), Toast.LENGTH_SHORT).show();

            }
        });

        update_button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                updateChildren(update_expense_amount, update_expense_title, update_expense_date, whichCatSelected);
            }
        });
        dialog.show();
    }

    @NonNull
    @Override
    public MyViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
        View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_view, parent, false);
        return new MyViewHolder(v);
    }

    public static class MyViewHolder extends RecyclerView.ViewHolder {
        TextView expenseItem, expenseAmount, expenseDate;
        ImageView category;

        public MyViewHolder(@NonNull View itemView) {
            super(itemView);
            expenseItem = itemView.findViewById(R.id.recyclerItemView);
            expenseAmount = itemView.findViewById(R.id.recyclerAmountView);
            expenseDate = itemView.findViewById(R.id.recyclerDateView);
            category = itemView.findViewById(R.id.recyclerCategory);
        }
    }


来源: stackexchange

问:
linking an image and image map each located on a different page
Is it possible to link an image map from one page to an img within a different page using usemap?

I have my image on "first page" and got the image map on "second page" and I want to link em using usemap attribute, I know that the hash symbol before the map name in usemap value is to indicates that this map exists in this page so I was wondering if I can, in this case, link an image map from another page

here is what I have done :
this is from the first page which contains the img only, this page name is "first.html"

```<code>    <img src="https://i.pinimg.com/564x/c5/79/c0/c579c0ebf4c0ea8f7e7f932c87af1cce.jpg" alt="product" usemap="second.html#mapo">
</code>```

and this is from the second page which contains the img map only, this page name is "second.html"

```<code>    <map name="mapo">
        <area shape="rect" coords="390,417,172,191"  href="https://www.pinterest.com/pin/506655026846033319/">
    </map>
</code>```

both pages/html files r in the same folder

I tried what I mentioned above but it didn't work and I don't know why

ContentLicense: CC BY-SA 4.0

Body:
Is it possible to link an image map from one page to an img within a different page using usemap?

I have my image on "first page" and got the image map on "second page" and I want to link em using usemap attribute, I know that the hash symbol before the map name in usemap value is to indicates that this map exists in this page so I was wondering if I can, in this case, link an image map from another page

here is what I have done :
this is from the first page which contains the img only, this page name is "first.html"

and this is from the second page which contains the img map only, this page name is "second.html"

    <map name="mapo">
        <area shape="rect" coords="390,417,172,191"  href="https://www.pinterest.com/pin/506655026846033319/">
    </map>

both pages/html files r in the same folder

I tried what I mentioned above but it didn't work and I don't know why


问:
Palindrome function- expected different outputs - javascript
Challenge received: String Challenge
Have the function stringchallenge str take the str parameter being passed and determine if it is possible to create a palindromic string or minimum length 3 characters by removing 1 or 2 characters. For example: if str is 'abjchba' then you can remove the characters jc to produce abba which is a palindrome. For this example your program should return the Two characters that were removed with no delimiter and in the order they appear in the string. so jc. If 1 or 2 characters cannot be remove to produce a palindrome, then return the string not possible.
If the input string is already a palindrome, your program should return the string palindrome. Your program should always remove the characters that appear earlier in the string. In the
example above, you can also remove ch to form a palindrome but jc appears first, so the correct answer is jc. The input will only contain lowercase alphabetic characters. Your program should always attempt to create the longest palindromic substring by removing 1 or 2 characters see
second sample test case as an example. The 2 characters you remove do not have to be adjacent in the string.

My question is, what should I do to get the function to give the expected output when the substring has been removed to create the palindrome? Can someone help me please???

```<code>function StringChallenge(str) {
  if(str === str.split("").reverse().join("")) {return str;};
  let result = "";
  for (let i = 0; i < str.length; i++) {
    let items = str[i];
    for (let j = i + 1; j < str.length; j++) {
      items += str[j];
      if (items === items.split("").reverse().join("")) {
        if ( result.length < items.length) {result = items;}
      }
    }
  }
  return result.length < 3 ? "not possible" : result ;
}
console.log(StringChallenge("kjjjhjjj")); // output expected "k" - output received "jjjhjjj"
console.log(StringChallenge("ana")); // output expected "ana" - ok
console.log(StringChallenge("mmop")); // output expected "not possible" - ok

</code>```

Body:
Challenge received: String Challenge
Have the function stringchallenge str take the str parameter being passed and determine if it is possible to create a palindromic string or minimum length 3 characters by removing 1 or 2 characters. For example: if str is 'abjchba' then you can remove the characters jc to produce abba which is a palindrome. For this example your program should return the Two characters that were removed with no delimiter and in the order they appear in the string. so jc. If 1 or 2 characters cannot be remove to produce a palindrome, then return the string not possible.
If the input string is already a palindrome, your program should return the string palindrome. Your program should always remove the characters that appear earlier in the string. In the
example above, you can also remove ch to form a palindrome but jc appears first, so the correct answer is jc. The input will only contain lowercase alphabetic characters. Your program should always attempt to create the longest palindromic substring by removing 1 or 2 characters see
second sample test case as an example. The 2 characters you remove do not have to be adjacent in the string.

My question is, what should I do to get the function to give the expected output when the substring has been removed to create the palindrome? Can someone help me please???

function StringChallenge(str) {
  if(str === str.split("").reverse().join("")) {return str;};
  let result = "";
  for (let i = 0; i < str.length; i++) {
    let items = str[i];
    for (let j = i + 1; j < str.length; j++) {
      items += str[j];
      if (items === items.split("").reverse().join("")) {
        if ( result.length < items.length) {result = items;}
      }
    }
  }
  return result.length < 3 ? "not possible" : result ;
}
console.log(StringChallenge("kjjjhjjj")); // output expected "k" - output received "jjjhjjj"
console.log(StringChallenge("ana")); // output expected "ana" - ok
console.log(StringChallenge("mmop")); // output expected "not possible" - ok


问:
TransactionManagementError An error occurred in the current transaction. You can't execute queries until the end of the 'atomic' block. django project
I would like to add products or update them if they exist on the database. the data collected comes from an API, then I save it on my database that I created.

models.py

```<code>class Holl(models.Model):
   name=models.CharField(max_length=70,blank=True,null=True)
   service=models.CharField(max_length=255,blank=True,null=True)
   section=models.CharField(max_length=70,blank=True,null=True)

   class Meta:
      constraints=[
        models.UniqueConstraint(fields=['name', 'section'], name='unique_rows')
      ]
</code>```

views.py

```<code>url='http://myAPI/Holl/GetHoll'
x=requests.get(url)
contenu=x.json()
all_holls=contenu['comm']
for holl in all_holls:
  ins, _ = Holl.objects.update_or_create(name=holl['name'],service=holl['service'],
  section=holl['section'],defaults={'name':holl['name'],'service':holl['service'],'section':holl['section']})
  ins.save()
</code>```

After testing I get this error:An error occurred in the current transaction. You can't execute queries until the end of the 'atomic' block.

Body:
I would like to add products or update them if they exist on the database. the data collected comes from an API, then I save it on my database that I created.

models.py

class Holl(models.Model):
   name=models.CharField(max_length=70,blank=True,null=True)
   service=models.CharField(max_length=255,blank=True,null=True)
   section=models.CharField(max_length=70,blank=True,null=True)

   class Meta:
      constraints=[
        models.UniqueConstraint(fields=['name', 'section'], name='unique_rows')
      ]

views.py

url='http://myAPI/Holl/GetHoll'
x=requests.get(url)
contenu=x.json()
all_holls=contenu['comm']
for holl in all_holls:
  ins, _ = Holl.objects.update_or_create(name=holl['name'],service=holl['service'],
  section=holl['section'],defaults={'name':holl['name'],'service':holl['service'],'section':holl['section']})
  ins.save()

After testing I get this error:An error occurred in the current transaction. You can't execute queries until the end of the 'atomic' block.


问:
Exclude a directory from `podman/docker export` stream and save to a file
I have a container that I want to export as a .tar file. I have used a podman run with a tar --exclude=/dir1 --exclude=/dir2 … that outputs to a file located on a bind-mounted host dir. But recently this has been giving me some tar: .: file changed as we read it errors, which podman/docker export would avoid. Besides the export I suppose is  more efficient. So I'm trying to migrate to using the export, but the major obstacle is I can't seem to find a way to exclude paths from the tar stream.

If possible, I'd like to avoid modifying a tar archive already saved on disk, and instead modify the stream before it gets saved to a file.

I've been banging my head for multiple hours, trying useless advices from ChatGPT, looking at cpio, and attempting to pipe the podman export to tar --exclude … command. With the last I did have small success at some point, but couldn't make tar save the result to a particularly named file.

Any suggestions?

(note: I do not make distinction between docker and podman here as their export command is completely the same, and it's useful for searchability)


问:
How to get Symfony clean URL after GET request
I'm working on a small Symfony project and I came across an issue I don't know how to fix. I'm performing a database search via a GET request, and I'm looking for articles that are part of categories. I can select many categories and press "search", then it will return only the specific articles.

The feature is working great, but my URL isn't... "clean", I think. Working on localhost, this is what I see, for example, when I look for category "vocabulary":

```<code>localhost:8000/blog/?q=&categories[]=125
</code>```

The q parameter is here to return articles when I look for a specific text (with an input field), but I think it shouldn't appear if the research only concerns categories. Right?

Also, display categories[]=125 is weird. The user should see something like categories=vocabulary&categories=grammar&categories... or something like this (of course, trying to avoid the repetition of "categories" in the URL.

How can I do this? This is what my code looks like in the repository:

```<code>/**
     * Find articles related to search
     */
    public function findSearch(SearchData $search): PaginationInterface
    {
        $query = $this
            ->createQueryBuilder('a')
            ->select('a', 'c')
            ->join('a.categories', 'c');

        // Handling text search
        if (null !== $search->q && !empty($search->q)) {
            $query = $query
                ->andWhere('a.title LIKE :q')
                ->setParameter('q', "%{$search->q}%");
        }

        // Handling categories
        if (!empty($search->categories)) {
            $query = $query
                ->andWhere('c.id IN (:categories)')
                ->setParameter('categories', $search->categories);
        }

        $query = $query->getQuery();

        return $this->paginator->paginate(
            $query,
            $search->page,
            9
        );
    }
</code>```

And here is what my controller looks like:

```<code>#[Route('/', name: 'blog_index')]
    public function index(ArticleRepository $articleRepository, Request $request): Response
    {
        $data = new SearchData();
        $data->page = $request->get('page', 1);
        $form = $this->createForm(SearchType::class, $data);
        $form->handleRequest($request);
        $articles = $articleRepository->findSearch($data);

        return $this->render('blog/index.html.twig', [
            'form' => $form,
            'articles' => $articles,
        ]);
    }
</code>```

If you need more info in order to help me, please ask.

Thanks in advance!

Body:
I'm working on a small Symfony project and I came across an issue I don't know how to fix. I'm performing a database search via a GET request, and I'm looking for articles that are part of categories. I can select many categories and press "search", then it will return only the specific articles.

The feature is working great, but my URL isn't... "clean", I think. Working on localhost, this is what I see, for example, when I look for category "vocabulary":

localhost:8000/blog/?q=&categories[]=125

The q parameter is here to return articles when I look for a specific text (with an input field), but I think it shouldn't appear if the research only concerns categories. Right?

Also, display categories[]=125 is weird. The user should see something like categories=vocabulary&categories=grammar&categories... or something like this (of course, trying to avoid the repetition of "categories" in the URL.

How can I do this? This is what my code looks like in the repository:

/**
     * Find articles related to search
     */
    public function findSearch(SearchData $search): PaginationInterface
    {
        $query = $this
            ->createQueryBuilder('a')
            ->select('a', 'c')
            ->join('a.categories', 'c');

        // Handling text search
        if (null !== $search->q && !empty($search->q)) {
            $query = $query
                ->andWhere('a.title LIKE :q')
                ->setParameter('q', "%{$search->q}%");
        }

        // Handling categories
        if (!empty($search->categories)) {
            $query = $query
                ->andWhere('c.id IN (:categories)')
                ->setParameter('categories', $search->categories);
        }

        $query = $query->getQuery();

        return $this->paginator->paginate(
            $query,
            $search->page,
            9
        );
    }

And here is what my controller looks like:

#[Route('/', name: 'blog_index')]
    public function index(ArticleRepository $articleRepository, Request $request): Response
    {
        $data = new SearchData();
        $data->page = $request->get('page', 1);
        $form = $this->createForm(SearchType::class, $data);
        $form->handleRequest($request);
        $articles = $articleRepository->findSearch($data);

        return $this->render('blog/index.html.twig', [
            'form' => $form,
            'articles' => $articles,
        ]);
    }

If you need more info in order to help me, please ask.

Thanks in advance!


问:
Chrome deleting cookies and cache
Every time I close my Chrome browser, the sync pauses, and I'm asked to accept cookies on every single site I visit, as well as having to sign in.

I have "All cookies allowed" on, I have "delete cookies and cache when browser closes" off.

One forum said it's probably an extension I have, so I deleted all extensions on the profile I'm on now.

Are there some sort of global settings for all Google profiles that are at play?

I've tried:

Cookies on

Cache and cookies when closed, off

deleting all extensions

Turning cookies off, clearing cache, turning back on, and clearing cache etc.

Title: Chrome deleting cookies and cache


问:
how to set dedicated cacerts for jvm
for the moment tomcat uses standard cacerts (/etc/pki/ca-trust/extracted/java) but I need to set a dedicated cacerts (eg /production) for my application. How to do it ?
thanks in advance

I tried to put cacerts in a dedicated directory (eg /production) and set configuration in catalina.sh like
JAVA_OPTS=$JAVA_OPTS -Djavax.net.ssl.keyStore=/production/cacerts -Djavax.net.ssl.keyStoreType=jks -Djavax.net.ssl.keyStorePassword=changeit
But it doesn't work tomcat continues to use cacerts from /etc/pki/ca-trust/extracted/java

Title: how to set dedicated cacerts for jvm


问:
QPushButton clicked events emits triggers callback multiple times
I designed my UI on "Qt 5 Designer", converted to pyqt5 with pyuic5. I am using PyCharm IDE.

QPushButton click calls callback function exactly three times when I push the buttons.

Below is my Main window flow (stripped from irrelevant sections)

```<code>class MainWindow(QMainWindow):
    def __init__(self):
        super(MainWindow, self).__init__()

        self.ui = Ui_MainWindow()
        self.ui.setupUi(self)

        self.ui.btn_record.clicked.connect(self.on_btn_record_clicked)  # event

    def on_btn_record_clicked(self):
        print(f"click: {self.clickcounter} {time.time()}")

if __name__ == "__main__":
    app = QApplication(sys.argv)
    widget = MainWindow()
    widget.show()
    sys.exit(app.exec_())
</code>```

When connect event is commented out, the code still works, but callback function is called 2 times this time. this 2 emissions occur when i release the mouse button.

When I rename the callback function to, lets say "on_MY_btn_record_clicked" the program runs as intended. (only single callback)

Qt designer "signals/slots editor" is empty

the name "btn_record" is the same with the Qt Designer QWidget name for QPushButton.

As far as I understand, Qt, somehow, generates default callback function with the name "on_btn_record_clicked" with "pass" and when I create my own function with the same name it overwrites the default callback.

This happens only with QPushButton. other widgets are not effected.

searching through entire projects returns only my callback function.

what can be the reason?
renaming callback function is a solution, but I think this will leave default callback functions with pass still called.

Body:
I designed my UI on "Qt 5 Designer", converted to pyqt5 with pyuic5. I am using PyCharm IDE.

QPushButton click calls callback function exactly three times when I push the buttons.

Below is my Main window flow (stripped from irrelevant sections)

class MainWindow(QMainWindow):
    def __init__(self):
        super(MainWindow, self).__init__()

        self.ui = Ui_MainWindow()
        self.ui.setupUi(self)

        self.ui.btn_record.clicked.connect(self.on_btn_record_clicked)  # event

    def on_btn_record_clicked(self):
        print(f"click: {self.clickcounter} {time.time()}")

if __name__ == "__main__":
    app = QApplication(sys.argv)
    widget = MainWindow()
    widget.show()
    sys.exit(app.exec_())

When connect event is commented out, the code still works, but callback function is called 2 times this time. this 2 emissions occur when i release the mouse button.

When I rename the callback function to, lets say "on_MY_btn_record_clicked" the program runs as intended. (only single callback)

Qt designer "signals/slots editor" is empty

the name "btn_record" is the same with the Qt Designer QWidget name for QPushButton.

As far as I understand, Qt, somehow, generates default callback function with the name "on_btn_record_clicked" with "pass" and when I create my own function with the same name it overwrites the default callback.

This happens only with QPushButton. other widgets are not effected.

searching through entire projects returns only my callback function.

what can be the reason?
renaming callback function is a solution, but I think this will leave default callback functions with pass still called.


问:
Teamcity auto build on project level
I have a Bitbucket project and it is designed in such a way, I have to create new repository as slide-project with copying base-framework-code(bfc) since each slide is unique in its own way(kind of animated learning slides) so utilizing the bfc to create a separate repo.

It looks like below - Solutions is project and it contains repositories(named as slides):

```<code>  -> Solutions |
               | -> Base-Framework-Code(bfc)(master)
               | -> slide-01  |(master)
                              |src
                              |bfc
                              |package.json
               | -> slide-02  |(develop)
                              |src
                              |bfc
                              |package.json
               | -> slide-03  |(feature)
                              |src
                              |bfc
                              |package.json

</code>```

My requirement is to implement TeamCity auto build feature in Solutions project itself.

When developers create a new slide-xx(a new repository), auto build should be triggered to that slide repo(for starters consider master).

Can I achieve this with TeamCity?
Please help with sharing any kind of resource.

PS. I'm new to TeamCity and still learning, I have gone through docs and demos and I know its working with specific repository with specific branches.

Thanks in Advance!

Title: Teamcity auto build on project level

Body:
I have a Bitbucket project and it is designed in such a way, I have to create new repository as slide-project with copying base-framework-code(bfc) since each slide is unique in its own way(kind of animated learning slides) so utilizing the bfc to create a separate repo.

It looks like below - Solutions is project and it contains repositories(named as slides):

  -> Solutions |
               | -> Base-Framework-Code(bfc)(master)
               | -> slide-01  |(master)
                              |src
                              |bfc
                              |package.json
               | -> slide-02  |(develop)
                              |src
                              |bfc
                              |package.json
               | -> slide-03  |(feature)
                              |src
                              |bfc
                              |package.json

My requirement is to implement TeamCity auto build feature in Solutions project itself.

When developers create a new slide-xx(a new repository), auto build should be triggered to that slide repo(for starters consider master).

Can I achieve this with TeamCity?
Please help with sharing any kind of resource.

PS. I'm new to TeamCity and still learning, I have gone through docs and demos and I know its working with specific repository with specific branches.

Thanks in Advance!


问:
React: How to refresh tree component on form submit?
I am displaying tree on the left side of the page. Every tree node is linked to the component. On click of node, using routing, I am opening a component on the right side of the page. All the components on the right side have form. How to refresh a tree on the left side of page without refreshing the form component on the right.
page contains two components: Left Part of Page: ProductsTreeView
Right Part of Page Add_Category component. Form submit Add_Category without refresh right part of page, how to refresh treeview on the left side of page.

Please find the code in the sandbox. This is showing tree: https://codesandbox.io/s/shy-snow-nfce4i

Complete code is in this sandbox: https://codesandbox.io/s/summer-water-ouw2dn
Somehow this sandbox is not working.

Please help if I am adding a tree node using Add_Category,  form submit should not refresh add_category component, it just only refresh the tree in the left side of the page.

```<code>import React, { Component, createRef } from "react";
import XMLParser from "react-xml-parser";
import { Link } from "react-router-dom";
import styled from "styled-components";
import plus from "./plus.gif";
import minus from "./minus.gif";
import paper from "./paper.gif";

const tree = `
<?xml version="1.0" standalone="yes"?>

<tree>

       <entity id="e11" key-id="1" link-page-name="Add_Category">
              <description>Service</description>
              <image>plus.gif</image>
              <imageOpen>minus.gif</imageOpen>
              <entity id="e248" key-id="48" link-page-name="Edit_Category">
                     <description>A_test1_test1</description>
                     <image>plus.gif</image>
                     <imageOpen>minus.gif</imageOpen>
                     <entity id="e3717" key-id="717" link-page-name="Edit_Product">
                           <description>A_SubItem1</description>
                           <image>plus.gif</image>                      <imageNode>de.gif</imageNode>
                           <imageOpen>minus.gif</imageOpen>
                           <entity id="e45546" key-id="5546" link-page-name="Edit_ProdTemplate">
                                  <description>A_Test_Template</description>
                                  <image>paper.gif</image>
                                  <imageOpen>paper.gif</imageOpen>
                           </entity>
                     </entity>
              </entity>
              <entity id="e264" key-id="64" link-page-name="Add_Product">
              <description>111AAAA</description>
              <image>plus.gif</image>
              <imageOpen>minus.gif</imageOpen>
            </entity>
            <entity id="e256" key-id="56" link-page-name="Add_Product">
              <description>11323789</description>
              <image>plus.gif</image>
              <imageOpen>minus.gif</imageOpen>
            </entity>
              <entity id="e247" key-id="47" link-page-name="Edit_Category">
                     <description>A_test6</description>
                     <image>plus.gif</image>
                     <imageOpen>minus.gif</imageOpen>

                     <entity id="e3716" key-id="716" link-page-name="Edit_Product">
                           <description>A_Item</description>
                           <image>plus.gif</image>
                           <imageOpen>minus.gif</imageOpen>
                           <entity id="e45545" key-id="5545" link-page-name="Edit_ProdTemplate">
                                  <description>temp1</description>
                                  <image>paper.gif</image>
                                  <imageOpen>paper.gif</imageOpen>

                           </entity>

                     </entity>

              </entity>

       </entity>

       <entity id="e12" key-id="2" link-page-name="Add_Category">

              <description>Sales</description>

              <image>plus.gif</image>

              <imageOpen>minus.gif</imageOpen>

              <entity id="e230" key-id="30" link-page-name="Edit_Category">

                     <description>Gift Cards</description>

                     <image>plus.gif</image>
                  <imageOpen>minus.gif</imageOpen>

                     <entity id="e3421" key-id="421" link-page-name="Edit_Product">

                           <description>Sample Card</description>

                           <image>plus.gif</image>
                           <imageOpen>minus.gif</imageOpen>

                           <entity id="e43308" key-id="3308" link-page-name="Edit_ProdTemplate">

                                  <description>greeting temp</description>

                                  <image>paper.gif</image>

                                  <imageOpen>paper.gif</imageOpen>

                           </entity>

                     </entity>

                     <entity id="e3422" key-id="422" link-page-name="Edit_Product">

                           <description>De Card</description>

                           <image>plus.gif</image>
                           <imageOpen>minus.gif</imageOpen>

                           <entity id="e43309" key-id="3309" link-page-name="Edit_ProdTemplate">

                                  <description>NS Temp</description>

                                  <image>paper.gif</image>

                                  <imageOpen>paper.gif</imageOpen>

                           </entity>

                     </entity>

              </entity>

              <entity id="e215" key-id="15" link-page-name="Edit_Category">

                     <description>Chck</description>

                     <image>plus.gif</image>

                     <imageOpen>minus.gif</imageOpen>

                     <entity id="e3671" key-id="671" link-page-name="Edit_Product">

                           <description>Add item</description>

                           <image>plus.gif</image>
                           <imageOpen>minus.gif</imageOpen>

                           <entity id="e45438" key-id="5438" link-page-name="Edit_ProdTemplate">

                                  <description>Ahhhh</description>

                                  <image>paper.gif</image>

                                  <imageOpen>paper.gif</imageOpen>

                           </entity>

                     </entity>

                     <entity id="e3450" key-id="450" link-page-name="Edit_Product">
                           <description>Advtttt</description>
                           <image>plus.gif</image>
                           <imageOpen>minus.gif</imageOpen>
                           <entity id="e43577" key-id="3577" link-page-name="Edit_ProdTemplate">
                                  <description>gggggg</description>
                                  <image>paper.gif</image>
                                  <imageOpen>paper.gif</imageOpen>
                           </entity>
                     </entity>
              </entity>
       </entity>

</tree>
`;

const StyledLI = styled.li`
  list-style-type: none;

  ::before {
    content: "";

    display: inline-flex;

    width: 16px;

    height: 16px;

    ${({ expanded, isPaper }) =>
      `background: url(${
        isPaper === paper ? paper : expanded ? minus : plus
      })};`};
  }
`;

class ProductsTreeView extends Component {
  constructor(props) {
    super(props);

    this.treeView = createRef();
  }

  render() {
    return (
      <div id="TreeView">
        <TreeView
          ref={this.treeView}
          setCurrentNode={this.props.setCurrentNode}
        />
      </div>
    );
  }
}

class Node {
  description = "n/a";

  id = -1;

  key_id = -1;

  linkpagename = "";

  icon = "";

  isActive = false;

  nodes = [];

  constructor(description, id, key_id, icon, linkpagename) {
    this.description = description;

    this.id = id;

    this.key_id = key_id;

    this.icon = icon;

    this.linkpagename = linkpagename;
  }

  static nodesFromXml(xml) {
    const map = (entity, nodes) => {
      const id = entity.attributes["id"];

      const key_id = entity.attributes["key-id"];

      const descriptionText =
        entity.children[
          entity.children.findIndex((child) => child.name === "description")
        ].value;

      const entities = entity.children.filter(
        (child) => child.name === "entity"
      );

      var linkPageName = entity.attributes["link-page-name"];

      linkPageName = linkPageName.replace(".aspx", "");

      const icon =
        entity.children[
          entity.children.findIndex((child) => child.name === "imageOpen")
        ].value;

      const node = new Node(descriptionText, id, key_id, icon, linkPageName);

      nodes.push(node);

      entities.forEach((entity) => map(entity, node.nodes));
    };

    const parsedData = new XMLParser().parseFromString(xml);

    const entities = parsedData.children.filter(
      (child) => child.name === "entity"
    );

    const nodes = [];

    entities.forEach((entity) => map(entity, nodes));

    return nodes;
  }
}

class TreeView extends React.Component {
  constructor(props) {
    super(props);

    this.state = {
      //  nodes: []
      nodes: Node.nodesFromXml(tree)
    };

    this.toggleNode = this.toggleNode.bind(this);

    this.CollapseAll = this.CollapseAll.bind(this);

    this.ExpandAll = this.ExpandAll.bind(this);
  }

  componentDidMount() {
    // axios
    //   .get(tree, { "Content-Type": "application/xml; charset=utf-8" })
    //   .then((response) =>{
    //     console.log({ response })
    //     // this.setState({ nodes: Node.nodesFromXml(response.data) })
    //   })
    //   .catch((error) => console.error("Error:", error));
  }

  render() {
    const nodes = this.state.nodes;

    return (
      <div>
        <table width="100%">
          <tr>
            <td width="50%" align="left">
                <b>Products</b>
            </td>
            <td width="50%" style={{ textAlign: "right" }}></td>
          </tr>
        </table>

        <ul>
          {nodes.map((node) => (
            <TreeNode
              id={node.id}
              key={node.key_id}
              node={node}
              onToggle={this.toggleNode}
              setCurrentNode={this.props.setCurrentNode}
            />
          ))}
        </ul>
      </div>
    );
  }

  toggleNode(node) {
    const { nodes } = this.state;

    this.props.setCurrentNode(node);

    function _toggleNode(currentNode, node, isActive) {
      if (isActive !== undefined) {
        currentNode.isActive = isActive;
      } else if (currentNode.id === node.id) {
        if (currentNode.key_id === node.key_id) {
          currentNode.isActive = !currentNode.isActive;
        }
      }

      currentNode.nodes.forEach((childNode) =>
        _toggleNode(childNode, node, currentNode.isActive ? undefined : false)
      );
    }

    nodes.forEach((currentNode) => _toggleNode(currentNode, node));

    this.setState((state) => (state.nodes = nodes));
  }

  CollapseAll() {
    const { nodes } = this.state;

    function _collapseAll(currentNode) {
      currentNode.isActive = false;

      currentNode.nodes.forEach((childNode) => _collapseAll(childNode));
    }

    nodes.forEach((currentNode) => _collapseAll(currentNode));

    this.setState((state) => (state.nodes = nodes));
  }

  ExpandAll() {
    const { nodes } = this.state;

    function _expandAll(currentNode) {
      currentNode.isActive = true;

      currentNode.nodes.forEach((childNode) => _expandAll(childNode));
    }

    nodes.forEach((currentNode) => _expandAll(currentNode));

    this.setState((state) => (state.nodes = nodes));
  }
}

class TreeNode extends React.Component {
  render() {
    const { node, onToggle } = this.props;

    const activeChildren =
      node.isActive && node.nodes.length ? (
        <ul style={{ paddingLeft: "1.8rem" }}>
          {node.nodes.map((node) => (
            <TreeNode
              id={node.id}
              key={node.key_id}
              node={node}
              onToggle={onToggle}
            />
          ))}
        </ul>
      ) : null;

    return (
      <Link
        to={node.linkpagename}
        key={node.key_id}
        onClick={(event) => {
          event.stopPropagation();

          onToggle(node);
        }}
        style={{ textDecoration: "none", color: "#000000" }}
      >
        <StyledLI
          id={node.id}
          expanded={node.isActive}
          isPaper={node.icon}
          isLeaf={!node.nodes.length}
        >
          {node.description}

          {/*- {node.key_id} - {node.linkpagename}*/}

          {activeChildren}
        </StyledLI>
      </Link>
    );
  }
}

export default ProductsTreeView;
------------------------Add_Category.js

import React from 'react'

export class Add_Category extends React.Component {

       constructor(props) {

             super(props);

             this.state = {

                    ID: "",

                    CategoryName: "",
                    ValidationStatus:"",

             };

             this.handleChange = this.handleChange.bind(this);

             this.handleSubmit = this.handleSubmit.bind(this);

       }

       handleChange(event) {

             this.setState({ CategoryName: event.target.value });

       }

       handleSubmit(event) {

             event.preventDefault();

       const ID = this.props.key_id;

                    const CategoryName    = this.state.CategoryName;

                    const data = {

                                        ID,

                                        CategoryName

                    }

                    fetch("url", {

                           method: 'POST',

                           headers: { 'Content-Type': 'application/json' },

                           credentials: 'include',

                           body: JSON.stringify(data),

                    })

                           .then(response => response.json())

                           .then((data) => {

                                 this.setState({

                                        ValidationStatus: data

                                 })

                           })

                           .then(response => { window.location.href = "/"; })

                           .catch(error => console.error('Error:', error)) ;

             }

       }

       render() {

        return (

                    <div>
  <form onSubmit={this.handleSubmit}>

<input type="text" value={this.state.CategoryName} onChange={this.handleChange} size="50" maxLength="50" />
        <button type="Submit" className="SaveButton">Submit</button>

</form>

</div>

);

}

}

export default Add_Category;
-------------------------Home.js
import React, { createRef } from "react";

import { TabContent, TabPane, Nav, NavItem, NavLink } from "reactstrap";

import { Route } from "react-router-dom";

import classnames from "classnames";

import "./styles.css";

import ProductsTree from "./ProductsTreeView";
import Add_Category from "./Add_Category";

const initialState = {
  currentNode: {},

  data: "",

  activeTab: "1"
};

class Home extends React.Component {
  constructor(props) {
    super(props);

    this.toggle = this.toggle.bind(this);

    this.state = initialState;

    this.setCurrentNode = this.setCurrentNode.bind(this);

    this.productsTree = createRef();
  }

  setCurrentNode(node) {
    this.setState({ currentNode: node });
  }

  toggle(tab) {
    if (this.state.activeTab !== tab) {
      this.setState({
        activeTab: tab
      });
    }

    this.productsTree.current.treeView.current.CollapseAll();
  }

  ExpandAll() {
    this.productsTree.current.treeView.current.ExpandAll();
  }

  CollapseAll() {
    this.productsTree.current.treeView.current.CollapseAll();
  }

  render() {
    return (
      <div>
        <table className="Container">
          <tbody>
            <tr width="100%">
              <td className="TreeContainer">
                <table width="100%" border="0" cellSpacing="0" cellPadding="0">
                  <tbody>
                    <tr className="trIndex_Products" width="100%">
                      <td align="left" nowrap="true">
                        <Nav tabs height="15px">
                          <NavItem>
                            <NavLink
                              className={classnames({
                                active: this.state.activeTab === "1"
                              })}
                              onClick={() => {
                                this.toggle("1");
                              }}
                            >
                              <b>Products</b>
                            </NavLink>
                          </NavItem>
                          <NavItem>
                            <NavLink
                              className={classnames({
                                active: this.state.activeTab === "2"
                              })}
                              onClick={() => {
                                this.toggle("2");
                              }}
                            >
                              <b>Sales</b>
                            </NavLink>
                          </NavItem>
                          <NavItem>
                            <NavLink
                              onClick={() => {
                                this.ExpandAll();
                              }}
                            >
                              <b>Expand</b>
                            </NavLink>
                          </NavItem>{" "}

                          <NavItem>
                            <NavLink
                              onClick={() => {
                                this.CollapseAll();
                              }}
                            >
                              <b>Minimize</b>
                            </NavLink>
                          </NavItem>
                        </Nav>
                      </td>
                    </tr>
                  </tbody>
                </table>{" "}
                <br />
                <TabContent activeTab={this.state.activeTab}>
                  <TabPane tabId="1">
                    <div id="ProdTree" className="tree">
                      <ProductsTree
                        ref={this.productsTree}
                        setCurrentNode={this.setCurrentNode}
                      />
                    </div>
                  </TabPane>

                  <TabPane tabId="2">
                    <div className="tree"></div>
                  </TabPane>
                </TabContent>
              </td>

              <td className="BodyContainer">
                <table width="100%" border="0" cellSpacing="0" cellPadding="0">
                  <tbody>
                    <tr width="100%">
                      <td>
                        <Route path="/Add_Category">
                          <Add_Category
                            key_id={this.state.currentNode.key_id}
                          />
                        </Route>
                      </td>
                    </tr>
                  </tbody>
                </table>
              </td>
            </tr>
          </tbody>
        </table>
      </div>
    );
  }
}

export default Home;
</code>```

Body:
I am displaying tree on the left side of the page. Every tree node is linked to the component. On click of node, using routing, I am opening a component on the right side of the page. All the components on the right side have form. How to refresh a tree on the left side of page without refreshing the form component on the right.
page contains two components: Left Part of Page: ProductsTreeView
Right Part of Page Add_Category component. Form submit Add_Category without refresh right part of page, how to refresh treeview on the left side of page.

Please find the code in the sandbox. This is showing tree: https://codesandbox.io/s/shy-snow-nfce4i

Complete code is in this sandbox: https://codesandbox.io/s/summer-water-ouw2dn
Somehow this sandbox is not working.

Please help if I am adding a tree node using Add_Category,  form submit should not refresh add_category component, it just only refresh the tree in the left side of the page.

import React, { Component, createRef } from "react";
import XMLParser from "react-xml-parser";
import { Link } from "react-router-dom";
import styled from "styled-components";
import plus from "./plus.gif";
import minus from "./minus.gif";
import paper from "./paper.gif";

const tree = `
<?xml version="1.0" standalone="yes"?>

<tree>

       <entity id="e11" key-id="1" link-page-name="Add_Category">
              <description>Service</description>
              <image>plus.gif</image>
              <imageOpen>minus.gif</imageOpen>
              <entity id="e248" key-id="48" link-page-name="Edit_Category">
                     <description>A_test1_test1</description>
                     <image>plus.gif</image>
                     <imageOpen>minus.gif</imageOpen>
                     <entity id="e3717" key-id="717" link-page-name="Edit_Product">
                           <description>A_SubItem1</description>
                           <image>plus.gif</image>                      <imageNode>de.gif</imageNode>
                           <imageOpen>minus.gif</imageOpen>
                           <entity id="e45546" key-id="5546" link-page-name="Edit_ProdTemplate">
                                  <description>A_Test_Template</description>
                                  <image>paper.gif</image>
                                  <imageOpen>paper.gif</imageOpen>
                           </entity>
                     </entity>
              </entity>
              <entity id="e264" key-id="64" link-page-name="Add_Product">
              <description>111AAAA</description>
              <image>plus.gif</image>
              <imageOpen>minus.gif</imageOpen>
            </entity>
            <entity id="e256" key-id="56" link-page-name="Add_Product">
              <description>11323789</description>
              <image>plus.gif</image>
              <imageOpen>minus.gif</imageOpen>
            </entity>
              <entity id="e247" key-id="47" link-page-name="Edit_Category">
                     <description>A_test6</description>
                     <image>plus.gif</image>
                     <imageOpen>minus.gif</imageOpen>

                     <entity id="e3716" key-id="716" link-page-name="Edit_Product">
                           <description>A_Item</description>
                           <image>plus.gif</image>
                           <imageOpen>minus.gif</imageOpen>
                           <entity id="e45545" key-id="5545" link-page-name="Edit_ProdTemplate">
                                  <description>temp1</description>
                                  <image>paper.gif</image>
                                  <imageOpen>paper.gif</imageOpen>

                           </entity>

                     </entity>

              </entity>

       </entity>

       <entity id="e12" key-id="2" link-page-name="Add_Category">

              <description>Sales</description>

              <image>plus.gif</image>

              <imageOpen>minus.gif</imageOpen>

              <entity id="e230" key-id="30" link-page-name="Edit_Category">

                     <description>Gift Cards</description>

                     <image>plus.gif</image>
                  <imageOpen>minus.gif</imageOpen>

                     <entity id="e3421" key-id="421" link-page-name="Edit_Product">

                           <description>Sample Card</description>

                           <image>plus.gif</image>
                           <imageOpen>minus.gif</imageOpen>

                           <entity id="e43308" key-id="3308" link-page-name="Edit_ProdTemplate">

                                  <description>greeting temp</description>

                                  <image>paper.gif</image>

                                  <imageOpen>paper.gif</imageOpen>

                           </entity>

                     </entity>

                     <entity id="e3422" key-id="422" link-page-name="Edit_Product">

                           <description>De Card</description>

                           <image>plus.gif</image>
                           <imageOpen>minus.gif</imageOpen>

                           <entity id="e43309" key-id="3309" link-page-name="Edit_ProdTemplate">

                                  <description>NS Temp</description>

                                  <image>paper.gif</image>

                                  <imageOpen>paper.gif</imageOpen>

                           </entity>

                     </entity>

              </entity>

              <entity id="e215" key-id="15" link-page-name="Edit_Category">

                     <description>Chck</description>

                     <image>plus.gif</image>

                     <imageOpen>minus.gif</imageOpen>

                     <entity id="e3671" key-id="671" link-page-name="Edit_Product">

                           <description>Add item</description>

                           <image>plus.gif</image>
                           <imageOpen>minus.gif</imageOpen>

                           <entity id="e45438" key-id="5438" link-page-name="Edit_ProdTemplate">

                                  <description>Ahhhh</description>

                                  <image>paper.gif</image>

                                  <imageOpen>paper.gif</imageOpen>

                           </entity>

                     </entity>

                     <entity id="e3450" key-id="450" link-page-name="Edit_Product">
                           <description>Advtttt</description>
                           <image>plus.gif</image>
                           <imageOpen>minus.gif</imageOpen>
                           <entity id="e43577" key-id="3577" link-page-name="Edit_ProdTemplate">
                                  <description>gggggg</description>
                                  <image>paper.gif</image>
                                  <imageOpen>paper.gif</imageOpen>
                           </entity>
                     </entity>
              </entity>
       </entity>

</tree>
`;

const StyledLI = styled.li`
  list-style-type: none;

  ::before {
    content: "";

    display: inline-flex;

    width: 16px;

    height: 16px;

    ${({ expanded, isPaper }) =>
      `background: url(${
        isPaper === paper ? paper : expanded ? minus : plus
      })};`};
  }
`;

class ProductsTreeView extends Component {
  constructor(props) {
    super(props);

    this.treeView = createRef();
  }

  render() {
    return (

        <TreeView
          ref={this.treeView}
          setCurrentNode={this.props.setCurrentNode}
        />

    );
  }
}

class Node {
  description = "n/a";

  id = -1;

  key_id = -1;

  linkpagename = "";

  icon = "";

  isActive = false;

  nodes = [];

  constructor(description, id, key_id, icon, linkpagename) {
    this.description = description;

    this.id = id;

    this.key_id = key_id;

    this.icon = icon;

    this.linkpagename = linkpagename;
  }

  static nodesFromXml(xml) {
    const map = (entity, nodes) => {
      const id = entity.attributes["id"];

      const key_id = entity.attributes["key-id"];

      const descriptionText =
        entity.children[
          entity.children.findIndex((child) => child.name === "description")
        ].value;

      const entities = entity.children.filter(
        (child) => child.name === "entity"
      );

      var linkPageName = entity.attributes["link-page-name"];

      linkPageName = linkPageName.replace(".aspx", "");

      const icon =
        entity.children[
          entity.children.findIndex((child) => child.name === "imageOpen")
        ].value;

      const node = new Node(descriptionText, id, key_id, icon, linkPageName);

      nodes.push(node);

      entities.forEach((entity) => map(entity, node.nodes));
    };

    const parsedData = new XMLParser().parseFromString(xml);

    const entities = parsedData.children.filter(
      (child) => child.name === "entity"
    );

    const nodes = [];

    entities.forEach((entity) => map(entity, nodes));

    return nodes;
  }
}

class TreeView extends React.Component {
  constructor(props) {
    super(props);

    this.state = {
      //  nodes: []
      nodes: Node.nodesFromXml(tree)
    };

    this.toggleNode = this.toggleNode.bind(this);

    this.CollapseAll = this.CollapseAll.bind(this);

    this.ExpandAll = this.ExpandAll.bind(this);
  }

  componentDidMount() {
    // axios
    //   .get(tree, { "Content-Type": "application/xml; charset=utf-8" })
    //   .then((response) =>{
    //     console.log({ response })
    //     // this.setState({ nodes: Node.nodesFromXml(response.data) })
    //   })
    //   .catch((error) => console.error("Error:", error));
  }

  render() {
    const nodes = this.state.nodes;

    return (

                Products

          {nodes.map((node) => (
            <TreeNode
              id={node.id}
              key={node.key_id}
              node={node}
              onToggle={this.toggleNode}
              setCurrentNode={this.props.setCurrentNode}
            />
          ))}

    );
  }

  toggleNode(node) {
    const { nodes } = this.state;

    this.props.setCurrentNode(node);

    function _toggleNode(currentNode, node, isActive) {
      if (isActive !== undefined) {
        currentNode.isActive = isActive;
      } else if (currentNode.id === node.id) {
        if (currentNode.key_id === node.key_id) {
          currentNode.isActive = !currentNode.isActive;
        }
      }

      currentNode.nodes.forEach((childNode) =>
        _toggleNode(childNode, node, currentNode.isActive ? undefined : false)
      );
    }

    nodes.forEach((currentNode) => _toggleNode(currentNode, node));

    this.setState((state) => (state.nodes = nodes));
  }

  CollapseAll() {
    const { nodes } = this.state;

    function _collapseAll(currentNode) {
      currentNode.isActive = false;

      currentNode.nodes.forEach((childNode) => _collapseAll(childNode));
    }

    nodes.forEach((currentNode) => _collapseAll(currentNode));

    this.setState((state) => (state.nodes = nodes));
  }

  ExpandAll() {
    const { nodes } = this.state;

    function _expandAll(currentNode) {
      currentNode.isActive = true;

      currentNode.nodes.forEach((childNode) => _expandAll(childNode));
    }

    nodes.forEach((currentNode) => _expandAll(currentNode));

    this.setState((state) => (state.nodes = nodes));
  }
}

class TreeNode extends React.Component {
  render() {
    const { node, onToggle } = this.props;

    const activeChildren =
      node.isActive && node.nodes.length ? (

          {node.nodes.map((node) => (
            <TreeNode
              id={node.id}
              key={node.key_id}
              node={node}
              onToggle={onToggle}
            />
          ))}

      ) : null;

    return (
      <Link
        to={node.linkpagename}
        key={node.key_id}
        onClick={(event) => {
          event.stopPropagation();

          onToggle(node);
        }}
        style={{ textDecoration: "none", color: "#000000" }}
      >

      </Link>
    );
  }
}

export default ProductsTreeView;
------------------------Add_Category.js

import React from 'react'

export class Add_Category extends React.Component {

       constructor(props) {

             super(props);

             this.state = {

                    ID: "",

                    CategoryName: "",
                    ValidationStatus:"",

             };

             this.handleChange = this.handleChange.bind(this);

             this.handleSubmit = this.handleSubmit.bind(this);

       }

       handleChange(event) {

             this.setState({ CategoryName: event.target.value });

       }

       handleSubmit(event) {

             event.preventDefault();

       const ID = this.props.key_id;

                    const CategoryName    = this.state.CategoryName;

                    const data = {

                                        ID,

                                        CategoryName

                    }

                    fetch("url", {

                           method: 'POST',

                           headers: { 'Content-Type': 'application/json' },

                           credentials: 'include',

                           body: JSON.stringify(data),

                    })

                           .then(response => response.json())

                           .then((data) => {

                                 this.setState({

                                        ValidationStatus: data

                                 })

                           })

                           .then(response => { window.location.href = "/"; })

                           .catch(error => console.error('Error:', error)) ;

             }

       }

       render() {

        return (

  <form onSubmit={this.handleSubmit}>

<input type="text" value={this.state.CategoryName} onChange={this.handleChange} size="50" maxLength="50" />
        <button type="Submit" className="SaveButton">Submit</button>

</form>

);

}

}

export default Add_Category;
-------------------------Home.js
import React, { createRef } from "react";

import { TabContent, TabPane, Nav, NavItem, NavLink } from "reactstrap";

import { Route } from "react-router-dom";

import classnames from "classnames";

import "./styles.css";

import ProductsTree from "./ProductsTreeView";
import Add_Category from "./Add_Category";

const initialState = {
  currentNode: {},

  data: "",

  activeTab: "1"
};

class Home extends React.Component {
  constructor(props) {
    super(props);

    this.toggle = this.toggle.bind(this);

    this.state = initialState;

    this.setCurrentNode = this.setCurrentNode.bind(this);

    this.productsTree = createRef();
  }

  setCurrentNode(node) {
    this.setState({ currentNode: node });
  }

  toggle(tab) {
    if (this.state.activeTab !== tab) {
      this.setState({
        activeTab: tab
      });
    }

    this.productsTree.current.treeView.current.CollapseAll();
  }

  ExpandAll() {
    this.productsTree.current.treeView.current.ExpandAll();
  }

  CollapseAll() {
    this.productsTree.current.treeView.current.CollapseAll();
  }

  render() {
    return (

                          <NavItem>
                            <NavLink
                              className={classnames({
                                active: this.state.activeTab === "1"
                              })}
                              onClick={() => {
                                this.toggle("1");
                              }}
                            >
                              Products
                            </NavLink>
                          </NavItem>
                          <NavItem>
                            <NavLink
                              className={classnames({
                                active: this.state.activeTab === "2"
                              })}
                              onClick={() => {
                                this.toggle("2");
                              }}
                            >
                              Sales
                            </NavLink>
                          </NavItem>
                          <NavItem>
                            <NavLink
                              onClick={() => {
                                this.ExpandAll();
                              }}
                            >
                              Expand
                            </NavLink>
                          </NavItem>{" "}

                          <NavItem>
                            <NavLink
                              onClick={() => {
                                this.CollapseAll();
                              }}
                            >
                              Minimize
                            </NavLink>
                          </NavItem>

{" "}

                <TabContent activeTab={this.state.activeTab}>
                  <TabPane tabId="1">

                      <ProductsTree
                        ref={this.productsTree}
                        setCurrentNode={this.setCurrentNode}
                      />

                  </TabPane>

                  <TabPane tabId="2">

                  </TabPane>
                </TabContent>

                        <Route path="/Add_Category">
                          <Add_Category
                            key_id={this.state.currentNode.key_id}
                          />
                        </Route>

    );
  }
}

export default Home;


问:
How to pass header information to a custom Jackson JSON deserializer
I have a custom Jackson JSON deserializer that converts a user's local timestamp to UTC:

Jackson Config:

```<code>@Configuration
public class JacksonConfiguration {
    @Bean
    public Module javaTimeModule() {
        JavaTimeModule module = new JavaTimeModule();
        module.addDeserializer(LocalDateTime.class, new JsonDatetimeDeserializer());
        module.addSerializer(LocalDateTime.class, new JsonDatetimeSerializer());

        return module;
    }
}
</code>```

Deserializer:

```<code>
public class JsonDatetimeDeserializer extends JsonDeserializer<LocalDateTime> {

    @Override
    public LocalDateTime deserialize(JsonParser jsonParser, DeserializationContext deserializationContext)
            throws IOException {

        String timestamp = jsonParser.getText();
        DateTimeFormatConstant dateTimeFormat = findDateTimeFormat(timestamp);
        LocalDateTime deserializedTime = null;

        if (dateTimeFormat != null) {
            switch (dateTimeFormat) {
                case ISO -> deserializedTime = localTimeToUtc(timestamp, dateTimeFormat.value());
                case ISO_WITH_OFFSET -> deserializedTime = zonedTimeWithOffsetToUtc(timestamp, dateTimeFormat.value());
                //Add more cases here as more formats are supported and added to DateTimeFormatConstant
            }
        }
        return deserializedTime;
    }

    private DateTimeFormatConstant findDateTimeFormat(String timestamp) {
        DateTimeFormatConstant currentFormat = null;
        for (DateTimeFormatConstant format : DateTimeFormatConstant.values()) {
            boolean isValidFormat = validateFormat(format.value(), timestamp);
            if (isValidFormat) {
                currentFormat = format;
                break;
            }
        }
        return currentFormat;
    }

    private boolean validateFormat(String format, String time) {
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern(format);
        boolean isValid;
        try {
            try {
                LocalDateTime localDateTime = LocalDateTime.parse(time, formatter);
                localDateTime.format(formatter);
                isValid = true;

            } catch (DateTimeException e) {
                ZonedDateTime zonedDateTime = ZonedDateTime.parse(time, formatter);
                zonedDateTime.format(formatter);
                isValid = true;
            }
        } catch (DateTimeParseException e) {
            isValid = false;
        }
        return isValid;
    }

    private LocalDateTime zonedTimeWithOffsetToUtc(String time, String format) {
        ZonedDateTime zonedDateTime = ZonedDateTime.parse(time, DateTimeFormatter.ofPattern(format));
        ZonedDateTime utcTime = zonedDateTime.withZoneSameInstant(ZoneOffset.UTC);

        return utcTime.toLocalDateTime();
    }

    private LocalDateTime localTimeToUtc(String time, String format) {

        AuthenticationDetails authDetails = (AuthenticationDetails) SecurityContextHolder.getContext().getAuthentication().getDetails();
        ZoneId zoneId = authDetails.getZoneId();

        LocalDateTime localDateTime = LocalDateTime.parse(time, DateTimeFormatter.ofPattern(format));
        Instant instant = localDateTime.atZone(zoneId).toInstant();
        ZonedDateTime zonedDateTimeUTC = ZonedDateTime.ofInstant(instant, ZoneId.of("Etc/UTC"));

        return zonedDateTimeUTC.toLocalDateTime();
    }
}

</code>```

I want to add a new case to this method whereby the user provides a time zone offset in the request headers. I'm not sure how I can pass a header from my controller to the custom deserializer. Any thoughts?

So far, I've looked into using ThreadLocal but I fear that may be dangerous in the future when multiple requests are being processed on the same thread.

Body:
I have a custom Jackson JSON deserializer that converts a user's local timestamp to UTC:

Jackson Config:

@Configuration
public class JacksonConfiguration {
    @Bean
    public Module javaTimeModule() {
        JavaTimeModule module = new JavaTimeModule();
        module.addDeserializer(LocalDateTime.class, new JsonDatetimeDeserializer());
        module.addSerializer(LocalDateTime.class, new JsonDatetimeSerializer());

        return module;
    }
}

Deserializer:

public class JsonDatetimeDeserializer extends JsonDeserializer<LocalDateTime> {

    @Override
    public LocalDateTime deserialize(JsonParser jsonParser, DeserializationContext deserializationContext)
            throws IOException {

        String timestamp = jsonParser.getText();
        DateTimeFormatConstant dateTimeFormat = findDateTimeFormat(timestamp);
        LocalDateTime deserializedTime = null;

        if (dateTimeFormat != null) {
            switch (dateTimeFormat) {
                case ISO -> deserializedTime = localTimeToUtc(timestamp, dateTimeFormat.value());
                case ISO_WITH_OFFSET -> deserializedTime = zonedTimeWithOffsetToUtc(timestamp, dateTimeFormat.value());
                //Add more cases here as more formats are supported and added to DateTimeFormatConstant
            }
        }
        return deserializedTime;
    }

    private DateTimeFormatConstant findDateTimeFormat(String timestamp) {
        DateTimeFormatConstant currentFormat = null;
        for (DateTimeFormatConstant format : DateTimeFormatConstant.values()) {
            boolean isValidFormat = validateFormat(format.value(), timestamp);
            if (isValidFormat) {
                currentFormat = format;
                break;
            }
        }
        return currentFormat;
    }

    private boolean validateFormat(String format, String time) {
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern(format);
        boolean isValid;
        try {
            try {
                LocalDateTime localDateTime = LocalDateTime.parse(time, formatter);
                localDateTime.format(formatter);
                isValid = true;

            } catch (DateTimeException e) {
                ZonedDateTime zonedDateTime = ZonedDateTime.parse(time, formatter);
                zonedDateTime.format(formatter);
                isValid = true;
            }
        } catch (DateTimeParseException e) {
            isValid = false;
        }
        return isValid;
    }

    private LocalDateTime zonedTimeWithOffsetToUtc(String time, String format) {
        ZonedDateTime zonedDateTime = ZonedDateTime.parse(time, DateTimeFormatter.ofPattern(format));
        ZonedDateTime utcTime = zonedDateTime.withZoneSameInstant(ZoneOffset.UTC);

        return utcTime.toLocalDateTime();
    }

    private LocalDateTime localTimeToUtc(String time, String format) {

        AuthenticationDetails authDetails = (AuthenticationDetails) SecurityContextHolder.getContext().getAuthentication().getDetails();
        ZoneId zoneId = authDetails.getZoneId();

        LocalDateTime localDateTime = LocalDateTime.parse(time, DateTimeFormatter.ofPattern(format));
        Instant instant = localDateTime.atZone(zoneId).toInstant();
        ZonedDateTime zonedDateTimeUTC = ZonedDateTime.ofInstant(instant, ZoneId.of("Etc/UTC"));

        return zonedDateTimeUTC.toLocalDateTime();
    }
}

I want to add a new case to this method whereby the user provides a time zone offset in the request headers. I'm not sure how I can pass a header from my controller to the custom deserializer. Any thoughts?

So far, I've looked into using ThreadLocal but I fear that may be dangerous in the future when multiple requests are being processed on the same thread.