Seam page actions and conversation - jsf

I have created my application using seam-gen. Seam-gen has created all the crud operations & forms for all my objects. They all inherit from seam's EntityHome.
I have this requirement that I need to create from an object A another object B (A has a List). So I need to redirect the user to the B form, save a new B object, and then redirect him to the original A form with the updated List contents.
I am a newbie in Seam and I am not sure how to implement this properly.
Edit: I am using seam version 2.2.2 final.

You can create an action class (similar to how entityHome works without the baggage that comes with it) to manage your contained entities and their behaviors. If no relationship exists between the entities you can make one here.
Refreshing the original list can be tricky, but once you have some code started post it.
So I would start with something like:
Class ActionBean {
ClassAObj classA;
List<ClassBObj> classBList;
public void methodThatLinksAandB() {
// ... stuff happens here
}
// getters and setter for view
// private worker methods
}

Related

Sharing components between views - how to improve my design?

I'm working on a JSF webapp which purpose is to wrap a command-line program.
One of its main functionality is the ability to share a session between users (eg. for courses purpose), so that when an input is sent to an instance of the application, the output sent to every subscriber for this session.
As a result of this design, the webapp is mainly composed of a view-scoped bean which will request a controller of the command-line application.
It has also been chosen to identify a session with the URL fragment (eg. mydomain/myapp/#SESSIONID), so that anyone using the URL with the same fragment will share inputs and outputs, using its own instance of the view-scoped bean but sharing the same controller
In order to push results to all subscribers, I'm using Primefaces Push. Results are primarily text that has to be appened to the webapp's terminal, but some commands lead to the programmatic creation of a JSF component.
In order to handle this, I just render these components to a string that I send to all subscribers.
Then, I realized that in order to handle ajax requests from components (and from every subscriber), the associated UIComponent needs to be added to the UIViewRoot in the context of (don't know how to express this) each view-scope bean.
As a matter of fact, I first tried to bind a "common container" (a UIForm) to a property of the view scoped bean, in which I would put the programmatically created components, but I obviously had to face the chicken/egg issue #BalusC talks about in his blog, because the component was added again on each ajax request. Setting javax.faces.PARTIAL_STATE_SAVING to false didn't help either (I'm using MyFaces 2.2.5)
So, as somewhat of a workaround, when the controller needs to create a new component, it basically adds the id of the component to the data pushed (in a HashMap converted to Json), and all subscribers will trigger (back) a remoteCommand to its own instance of the view-scoped bean, in order to update the "common container" from its own UIViewRoot.
This does work, but I don't like this way of doing it!
So:
would it be possible to handle this kind of sharing between view-scope beans (with the same name) which are stored in different HTTP sessions? I'm refering to this answer from #BalusC... maybe playing with javax.faces.ViewState - would it even be possible?
Is there a "magical" scope for my currently-view-scoped bean I could use?
Shall I rather use a completely different design?
Thanks!
If you want share data between all your application users you can use application scope.
If you still want to use view scope, you can connect your view scope with another application scope like this:
ApplicationView appView = BeanUtil.findBean("applicationView", FacesContext.getCurrentInstance());
import javax.faces.context.FacesContext;
public class BeanUtil {
#SuppressWarnings("unchecked")
public static <T> T findBean(String beanName, FacesContext context) {
return (T) context.getApplication().evaluateExpressionGet(context,
"#{" + beanName + "}", Object.class);
}
}

Orchard: Welding a ContentPart to all ContentTypes

I have a requirement where i need to weld a ContentPart to all the content types. Please guide me what is the best place to write this code.
I looked into the Orchard source code where InfosetPart is being welded with all content types in ContentHandlerBase's Activating method.
Following the InfosetPart weld mechanism i created one class inheriting from ContentHandlerBase and in Activating method i placed a break point with following condition which is getting hit again and again (more than once for one content type)
context.ContentType == "Page"
I'm not sure if it should be as it is because ideally it should hit this condition only once.
The way you are implementing it is correct. Your code is executed multiple times because content handlers are invoked for each content item, and not just for the content type. This also allows you to weld your part to only some of you content items, not all items of a specified type.
You wrote that you created a subclass of ContentHandlerBase. You should use ContentHandler as a base class.
Below is a simple code example how this should be done.
public class MyPartHandler : ContentHandler
{
protected override void Activating(ActivatingContentContext context) {
context.Builder.Weld<MyPart>();
}
}

How to override context.getUser()

for a my current project I would like to overide the context.getUser() method to return a custom pojo which extends the default object returned?
The reason I would like to do is so that I dont have to use the sessionScope technique of saving person specific data and just can call context.getUser() instead (which checks which user is logged on (or anonymous) and retrieves all data needed without.
I would not override context.getUser() - you don't know what else that may require. Have you looked at the userBean and or peopleBean from the extension library? You could use that to get any information you need, then if you need more, or want to create a custom class that extends those beans, install it as a scoped bean in your application, and then use it as the base for your own getUser().

Scalability and Thread Safety of Application Scoped ManagedBean Methods

During testing a weakness was exposed in how our app builds f:selectItems lists, specifically, entering really long names on some of our entities screws page alignment by making really wide selects.
Many of these selectItem lists are duplicated in multiple views and backing beans, so I'd like to consolidate their creation.
We already have an application scoped bean that provides List<SelectItem> for enums, and my initial thought was to place them there.
I have some questions, though. We're using jsf 1.2 (if that matters)
1) My understanding is that application scoped beans are singleton simply because a single instance is instantiated and placed in session context. They are not like EJB3 singletons in that only one thread can access any method, so multiple requests won't block trying to access different methods. Is that correct?
2) I suspect each method would have to be synchronized to prevent multiple threads calling the same method from clobbering each other. Is that the case even if the only class member accessed in the method is a threadsafe stateless #EJB?
Following is an implementation of one of them that would be used in 20 views. The implementations for 10 other entities would be similar. Also, the appropriate converters are registered.
public synchronized List<SelectItem> getAccountSelect(){
List<Account> list = new ArrayList<Account>(pemEJB.list(Account.class));
Collections.sort(list, new AccountByActiveByName());
List<SelectItem> result=new ArrayList<SelectItem>(list.size());
for(Account row : list){
result.add(new SelectItem(row,
StringUtil.prefixTruncate(row.getName(), MAX_ACCT_LENGTH, row.isActive())));
}
return result;
}
Any advice appreciated
If it's really mandatory to do the data loading in a getter instead of in the constructor/postconstruct, then there's definitely no point of making it an application scoped bean. Just make it a request scoped one where you do the data loading job in the constructor/postconstruct.
In the jsf applications I work on we load almost all of our reference data (values for selectOneMenues primarily) in Application scope beans and we set up the values in the Constructor of those beans. The data is then available to other managed beans and views via getters but is globalized and centralized for the application. Since the values are only read via getters there is no need for synchronization.
We then expose the beans as mbeans through jmx with a reload method so that they can be updated as needed. The reload method(s) are synchronized so as to block during the short reloads.
In your example above it seems like you could just return a Collection of selectItems so as long as the values are setup in advance you can use this method and still serve multiple threads just fine:
public List<SelectItem> getAccountSelectItems() {
return this.accountSelectItems;
}
Just add this private member to your bean:
private List<SelectItem> accountSelectItems;
and set it up in the constructor:
public AccountBean() {
List<Account> list = new ArrayList<Account>(pemEJB.list(Account.class));
Collections.sort(list, new AccountByActiveByName());
this.accountSelectItems = new ArrayList<SelectItem>(list.size());
for(Account row : list) {
this.accountSelectItems.add(new SelectItem(row, StringUtil.prefixTruncate(row.getName(), MAX_ACCT_LENGTH, row.isActive())));
}
}
If on the other hand this is data that is constantly changing and needs to be updated you might be better off just loading it per session or per request, though you can reload it periodically in application scope using Quartz or some other timer to keep the data reads from your data source down if real time is not an essential requirement for this data in your app. If you are reloading the data then you will want to synchronize those operations if you're using application scope.

how to avoid model code duplication with JSF and JPA

I'm new to JSF and am wondering if I got things right. Let's say I have a simple CMS that makes it possible to write pages.
First, I define a JPA entity called Page:
#Entity
public class Page {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
#Column
private Long id;
#Column private String title;
#Column private String content;
// getters & setters ...
}
Then I would like in a view to create Page-s. For that, it looks like I need a page bean of some sort. For now I handled things like this:
#Model
public class PageBean {
private Page page = new Page();
public String getTitle() {
return page.getTitle();
}
public void setTitle(String title) {
page.setTitle(title);
}
// rest of properties & getters & setters ...
public void save() {
// persist using EntityManager
}
}
My question is the following one: given that my JPA entity model and the model I want to use in the views are most of the time exactly the same, is there a way of avoiding to have to create a batch of getters & setters in the PageBean?
I read somewhere that you should not use a same bean as JPA entity and JSF model bean (because JSF does repeated calls to getters that may affect JPA), yet I do wonder if there is not a simpler way that would help avoiding this kind of code duplication. Especially when you've got an application with a large model and in many instances do not require anything special in the view beans, it looks like this can get quite cumbersome.
[...] given that my JPA entity model and the model I want to use in the views are most of the time exactly the same, is there a way of avoiding to have to create a batch of getters & setters in the PageBean?
I don't see the point of using a wrapper around an Entity and adding such a layer is indeed duplication. Just use the entity from your JSF page. Yes, this introduce some sort of coupling between the view and the domain but, in general, modifying the database usually means adding or removing fields on the view. In other words, I don't buy the "decoupling" argument and I've written enough extra layers, mapping code, boilerplate code, etc to favor the simple approach when possible.
I read somewhere that you should not use a same bean as JPA entity and JSF model bean (because JSF does repeated calls to getters that may affect JPA)
I'd be interested if you could provide a reference but a wrapper class (delegating calls to the entity) is not going to change anything if there is a problem somewhere.
Just in case, some additional resources:
EclipseLink/Examples/JPA/JSF Tutorial
It's not code duplication. The are no algorithms duplicated. The business logic is still in one place.
What your bean is doing is just connecting the View to the Domain model. This is good, it's part of the MVC pattern.
If you were using your JPA entity as your backing bean, you would be breaking the MVC pattern. For example, if one day instead of displaying a plain String you would need to add a Date to this String because the view requires so (i.e. interface requirements), are you going to write this view logic inside the JPA class? That does not make sense, mixing domain model and view model.
On the other hand, why the view has to know about how the domain is implemented? What if the domain values format change? (For example you save a timestamp String instead a date class in de Database for performance reasons). All you would need to do is just rewrite the method in the backing bean, it would take the timestamp and adapt it to a Date so everything would work as it was before. Just one change outside the JPA class. If you had it in the JPA class you would end up maintaining both logics in just one class (interface logic and domain logic).
What if you want to develop a new view (for example for mobile version)? Are you gonna add even more code to the JPA class? It would be better to keep the JPA as it was and create another Bean (that extends a common bean for both views) for the mobile version.
If after all this, you still want to not to write the getters and setters, you can do
#{myBean.page.title}
all you need is a getPage() inside the backing bean.

Resources