Win a copy of Murach's Python Programming this week in the Jython/Python forum!
  • Post Reply Bookmark Topic Watch Topic
  • New Topic

Use ServletContextAttribute or something else?  RSS feed

 
Ryan McClain
Ranch Hand
Posts: 153
1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I am making an application in which I have to make the model (the services) available to the entire application so that all beans can access it and call its methods during the life of the application.

I am using the following technologies:
view: JSF 2.x
beans: Spring 4.x beans

The design problem I am having is the following:

I came up with the idea of registering the model services as ServletContext attributes using my ServletContextListener, effectively making the services available to the entire application:



The problem I now face is code duplication and perhaps some other problems: in every JSF 2 bean that needs these services, I need to write the following code:



Wouldn't that be a code duplication problem? The first code piece of my UserBean was this:



And now my UserBean looks like this:


Shouldn't I just use @Autowired userService and @Autowired repairservice everywhere I want to use these services application-wide?
Or is this a problem because beans have a default scope of Request? I am confused.

I don't know if I am using a wrong approach on this.

Any help is greatly appreciated.
 
Tim Holloway
Bartender
Posts: 18531
61
Android Eclipse IDE Linux
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I apologise in advance, but any code example that won't fit on my screen without scrolling it probably won't get read. It's the price one pays for free help, so wherever possible, keep the samples as short as reasonably possible,

I'm going to do something foolish and assume that you are talking about an application-wide services bean, being a pure code bean (like a stateless session EJB), and with no internal state, since otherwise it can get messy when you have multiple users, regardless of what platforms you use.

In pure JSF, such a resource can be an application-scope backing bean. Which is also useful for holding shared objects common to all users, but it fits the above reguirements

You can also use a POJO static class. The downside of that is that it's hard-coded into the webapp, and thus can't be easily swapped out for testing.

Or you can use a Spring singleton bean. Essentially the same as the POJO static class, except that Spring manages it. If you have the Spring/JSF bridge in your faces-config, you can also reference it in EL expressions the same way that EL allows referencing JSF backing bean objects.

OK. I cheated and looked at your core ContextListener code. Nope, I usually wouldn't be doing that. I'd be doing one of the above. More flexible.

A general note: I have discovered - the hard way - that static classes full of static methods often end up making me regret that particualar design decision. Sooner or later, I almost inevitably need the flexibility of member access, either because it's easier to keep a bunch of context information in the bean in question or because I want to swap out some test/simulator code and don't want to have to hand-edit each and every line of code that refers to the static methods. Or both. So I generally try to use instance objects even for static functionality.
 
Ryan McClain
Ranch Hand
Posts: 153
1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I don't understand the Spring Singleton bean concept. My model is a dependency project outside of my web app and it will not be changed. Now, in my webapplicatoin, if I use @Autowired on my model, let's say @Autowired UserService userService @Autowired RepairService repairService, it seems my entire application can access it. In this case my SessionScoped backing bean is using these beans. I open up my browser and I navigate to my launched webapp, I log in (a function of my model) and I print something like ${repairService.allRepairs} and it works. I open up a completely different browser (FireFox instead of Chrome) and I do the same.. the repairs are still displayed correctly on the page. I don't understand this. So if I use the Spring applicationContext, I don't need to have an ApplicationScoped backing bean? The beans are just there up for grabs whenever I want them? I also need to make sure my code is thread-safe, but that's another concern.

Right now I am trying to understand if my model in the form of Spring beans is enough for the entire application to access it and if it's a good design.

 
Tim Holloway
Bartender
Posts: 18531
61
Android Eclipse IDE Linux
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
You keep using the term "model", but I don't think it means what you think it means.

Many of my JSF webapps have two different types of models. The UI model, which is JSF backing beans, and the ORM Data Model (Hibernate/JPA Entity objects). They're not generally interchangeable, although you can hang ORM model objects off of JSF model objects.

Spring's normal (default) object basis is Singleton objects, but it has the option to produce other types of objects as well, so I made it a point to stress that you'd want singletons if you want only one per application instance.

The Spring object factories are independent of the JSF object factory. And, in fact, of J(2)EE, entirely. Spring-manufactured objects have no inherent J2EE scope, although they behave similar to application-scope objects, other than not being kept in the ServletContext. Not that you couldn't use the Spring object factory to create a POJO, and then store the POJO in application scope, session scope, or whatever. Just that Spring is quite capable of locating the objects on its own.

I use Spring in my JSF apps to manufacture/locate a variety of objects. Email modules, Persistent Storage interfaces, call-outs to external web services - any complex function that could be best encapsulated in a POJO. I use Spring to do it, since these objects are not part of the UI layer of the application, they're services that can be invoked. And JSF only understands how (and when) to construct UI model objects, not general-purpose objects. Spring can handle them, but it's not directly tied into the JSF model object construction process (which is why @Autowired probably won't work on a JSF Managed Bean). So I use both, as appropriate.
 
Ryan McClain
Ranch Hand
Posts: 153
1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I know exactly what it means: the model project someone gave me so I use it in my web application. It has your classic project flow: services(interface) -> services(impl) -> dao(interface) -> dao(impl).

I add this model as a dependency project to my web project. The backing beans talk to this model through the service layer. The service layer accesses the dao layer. A small example: Userbean implements Serializable { @Autowired UserSerivce service; login(){ try { userService.loginUser(); return welcome.xhtml; } catch (UserException ex) { return index.xhtml; }. As you can see, the flow is like this in my project: JSF backing beans -> external model. Yes, I am invoking my external services.

@Autowired works on my beans because I am not using JSF Managed Beans, but rather Spring Beans (I use @Component etc.). This has been a design decision: front end: JSF view, back end: Spring beans.

For further clarity, here is a snippet of some relevant declarations in my web.xml:

 
It is sorta covered in the JavaRanch Style Guide.
  • Post Reply Bookmark Topic Watch Topic
  • New Topic
Boost this thread!