JSF/Seam - new component instance on submit? - java

And my confusion with JSF continues. This is a continuation of a question asked yesterday, but I feel it warrants a new question. I have a single seam component that expects a URL parameter to be injected for retrieving a List<String> from a method. This works perfectly on the first navigation to the page. The List is used to display many different selectOneRadio groups that populate a <h:form/>.
Now on the submit, I cannot get the URL parameter to be injected or otherwise set on the component! Adding <h:inputHidden/> causes FacesExceptions to be thrown.
Then I tried setting the List as an instance variable on the object, and when the subsequent call is made on the submit (which I also do not understand why that is done) I check to see if the variable is non-null: if it isn't, return it.
Now I found that a new instance of the component is created on submit!!!
getList() called
this.toString(): .BeanAction#5fd98420
#### This is when submit is clicked
getList() called
this.toString(): .BeanAction#22aacbce
The component has the following annotations:
Stateful
#Scope(ScopeType.CONVERSATION)
#Name("bean")
#Restrict("#{identity.loggedIn}")
Can someone explain why there is a new instance of the component created?
I'm really not quite sure how to go about handling this. I thought the hidden parameter would work, because that is how I would do it with straight HTML, and I'm a little surprised that its not working for JSF/Seam.

I hit upon the solution, but I still dont understand why it is required. By adding <S:conversationId/> to the <h:commandButton/> tag I am now getting the conversationId propagated across the form submit.
However, the seam documentation states:
If you don't do anything special, a non-faces request (a GET request for example)
will not propagate the conversation context and will be processed in a new
temporary conversation.
Which means Seam/JSF was treating my form submit as a "non-faces request". Why is that?

When you enter the page (or after the submit), do you see a conversation id in the url? I am concerned that perhaps the Seam Conversation is not being initialized correctly.

Related

Vaadin ComboBox clearing selection

I have a ComboBox defined as follows:
private final ComboBox classification = new ComboBox( "Class" );
classification.addItem("C");
classification.setItemCaption("C", "Company");
classification.addItem("S");
classification.setItemCaption("S", "Supplier");
classification.addItem("U");
classification.setItemCaption("U", "Customers");
classification.setRequired(true);
classification.setRequiredError("A user class must be chosen!");
classification.setFilteringMode(FilteringMode.CONTAINS);
classification.setTextInputAllowed(true);
Whenever I select any value from the dropdown, it immediately clears what I select. I don't even see it in the "ValueChange" listener.
What is weird is that I copied this form from another one that works perfectly, with a country dropdown. I am NOT picking an invalid value from the dropdown. Any idea what is happening?
If not, any idea where I would set a break point in debugger to see where it is getting cleared in ComboBox code? I tried this once, but sort of got lost in the details.
Ok, I found the answer to my own question. In my case, my problem was caused by the wrapper bean I was binding the fields too. My bean wraps two "sub-beans", if you will, one for input from an XML, one for output to an XML. The one for "input" should be filling the form ( calls "get" methods ), but the one for "output" should filling the data from the form ( calls "set" methods ). This is obviously not ideal, but this is the API I am stuck with. To fix it, I just made sure that all wrapper "get" methods checked "input" bean first, then "output" bean. For the "set" methods, I just made sure I set both the "input" and "output" beans. Like I said, not ideal.
To summarize: If you see your ComboBox value going away, making sure the bean you are binding to does not undo whatever the ComboBox sets in the corresponding "setter" and "getter" ( under the hood, I believe it sets it, then gets it again ).
Hopefully this helps someone not make the same mistake.

JSF One Session Per User

I just started learning with JSF and I'm wondering about this issue.
I have 16 Checkboxes. When I open the Page and my Brother is opening it too it seems like we have the same session. When I click one of the checkboxes it is checked on my brothers browser too.
The selected checkboxes are saved in a private ArrayList<String> selectedBoes = new ArrayList<String>();
My ManagedBean ist SessionScoped.
Why is this happening and how to avoid it?
My brothers session ID is cdbbb126e96060ddb924b9d5e591. Mine is cd9a5c4180bd9dfef0ec8db2ac4d
Then the only possible cause is that you're actually not storing them in the session scope. The symptoms indicate that you're either storing them in the application scope, or even that you declared it static (and thus the code in the question does not represent the real code at all; the code in your comments indicate that also less or more, you used a different property name, apparently you attempted to type it from top of head, you should not do that, you should copypaste the real code).
Note that when you're using CDI's #Named instead of JSF's #ManagedBean, then it would default to the application scope, unless otherwise specified with a javax.enterprise.context scope annotation. So if you're using JSF's own javax.faces.bean.SessionScoped annotation, which is not supported by CDI, then it would still be in the application scope.

Components not reloading on url change in Wicket 1.5(.2)?

I navigate to my application the first time with following URL:
.../homepage/?0&user=x
In debug mode I see wicket is nicely instantiating my panels and such (obviously).
if I change the URL to:
.../homepage/?0&user=y
then nothing happens, the panels are not re-initialized (for the new user => data of user x is still shown) nor are LoadableDetachable -or other models invoked.
However, if I change the URL to:
.../homepage/?1&user=y
then all panels are nicely initialized for user y
One step further, if you change the URL back to
.../homepage/?0&user=y
then again the data for user x is displayed.
It seems that Wicket does not care that arguments have changed in the URL to decide whether or not to reload components. AFAIK this was working fine in Wicket 1.4. I think I understand the logic behind this behavior but am not sure. Also, I would like to know how to force Wicket to reload if custom parameters change and how to remove that 'ugly' ?0 from the URL (if possible)?
This is the stateful nature of Wicket. The page is instantiated once, the parameters are parsed and so on. Later you pass different parameters to the already instantiated page but this time its constructor is not called at all and thus PageParameters are not updated. Changing to ?1 asks Wicket for page with id 1 and since there is no such Wicket instantiates a new instance and passes the new parameters. If you want to always have the latest request parameters then use getRequest().getRequestParameter("user") which will give you what you need.
Makes sense ?
To amend martin-g's answer: you should retrieve the request parameter in your model, and retrieve the correct user with the request parameter. Something like:
setModel(new LoadableDetachableModel<User>(){
public User load() {
String username = getRequest().getRequestParameter("user");
return userservice.byUsername(username);
}
}));
When you need dynamic data, almost always use models to solve your problem.
I think you can use onRender or onConfigure

Struts2 validation when using divs loaded from ajax

We have a Struts2 application using the <sx:tabbedpanel>. I know this has since been deprecated, but we have not yet had time to replace it.
We're populating the tabs by using the <sx:div> tag and specifying the href attribute, which makes an asynchronous call to the server to populate the contents of the tab. The downside to this is that we lose validation information like <s:actionerror>.
Here's what we think is happening... when the user performs an invalid action, the action class returns validation errors. When the resulting jsp is loaded, the validation messages are available. However, the <sx:div> then makes the asynchronous call back to the server to reload the contents. This time, the action class is just loading data to display, so it doesn't generate any validation messages. The results of this ajax call are then displayed in the browser, without any validation messages.
I've seen many examples on the web of using the <sx:div> tag this way within the tabbedpanel, so I'm guessing this is a problem that has been solved before, we just haven't found it.
Does anyone know of tutorials or examples that show how to do validation in this case?
Thanks for the help, I really appreciate it.
Would it make sense to put the errors outside of the tabbedpanel like:
<s:fielderror />
<sx:tabbedpanel...>
...
</sx:tabbedpanel>
Perhaps we can assist you a bit more if you can post some sample code or provide more info as to what kind of errors are expected and what the content of the tabbed panel is.
We found that we could populate the divs by using the <s:action> tag instead. This gets rendered at the time of the initial request, it does not make an ajax call later. Therefore, the JSPs have access to the validation messages and errors.

How should presentation tier (JSF) interoperate with services tier (Spring)?

I know that there are many different architectures exist. In this question I consider 3-tiers architecture (presentation-services (busyness logic)-data access layer (DAOs). And I want to concentrate on how presentation tier works with services tier.
The problem I met is standard. I have stateless services layer, and I think it should be stateless for the sake of scalability and performance.
I also have stateful presentation layer. For example, when user fills some form and inputed values don't pass validation, it's good practice to show all fields with inputed values and to point to incorrect fields.
So, imagine that we have FooBean with methods setFoo (Foo f), getFoo () and doSave (). Bean has Session scope.
And we want to save (persist) new instance of Foo. What we do is call method setFoo () and then call method doSave (). If saving failed than user will see just filled form with all inputed values (getFoo () method is called).
That's nice, but now imagine that user clicks Create Foo link, fills all fields, tries to save but doesn't pass validation? He will see filled form again. And then he clicks on 'Create Foo' again (he wants to create 2 Foo objects simultaneously). He will see filled form with pointed errors. But it's bad, because he didn't fill this (second, new) form yet.
If we change FooBean scope to Request, than we won't be able to show filled form when it's necessary (after saving failed).
So, what is the way out? What is the correct solution? It can be JSF-specific or general.
You need something called "conversation". There are a number of ways for achieving this.:
MyFaces orchestra
JBoss seam
A conversation is either automatically or manually managed scope that is greater than a request, but is smaller than a session. Ideally it should store your beans as long as they are needed to be stored - i.e. in one conversation. So from your example, the first conversation will end at the point the use navigates away from the first page.
MyFaces orchestra (I can't tell for seam) can also differentiate between different browser windows/tabs.

Categories

Resources