Session Scoped Controller Class ?

27 views
Skip to first unread message

Ralph Soika

unread,
Jun 19, 2018, 1:19:06 PM6/19/18
to MVC 1.0 Users Mailing List
I have a question about controllers and javax.enterprise.context.SessionScoped

I implemented a MVC 1.0  controller with looks like this:

@Controller
@Named
@SessionScoped
@Path("/connection")
public class ConnectionController implements Serializable {
 
private static final long serialVersionUID = 1L;
 
String url;

 
public ConnectionController() {

 
super();
 
}
 
public String getUrl() {
 
return url;
 
}

 
public void setUrl(String url) {
 
this.url = url;
 
}
     
....
}


This controller seems to work fine with Wildfly (RestEasy). It is instantiated once in a session. But running the same code in Payara/Glassfish (Jersey) the controller is created in each request - so it seems my annotation @SessionScoped is ignored? 
Is this normal, is this expected or am I doing something totally stupid here?

My application runs with javax.mvc-api 1.0-pr and ozark-resteasy 1.0.0-m03
....OK ...and now as I am writing this lines, it seems to be stupid... I think I have to use a ozark-jersey module here instead of ozark-resteasy?

But so I came to another question: In a situation, where I am building a general application to be deployed on wildfly or payara, do I need to create separate builds? Is this the correct way? I think I can do this with maven profiles....

And finally: I am absolutely fascinated how easy it is to build applications with MCV 1.0. I come from the JSF world and stared migrating form JSF to MVC. Once again: many thanks for this great framework!!

===
Ralph

Daniel Dias Dos Santos

unread,
Jun 19, 2018, 1:27:11 PM6/19/18
to jsr371...@googlegroups.com
Hi Ralph, 

to use with GlassFish / Payara have to use the ozark-jersey module.

in my presentations or example code I make a profile for both in the morning.

But I believe that for a real solution, maybe this is a problem.


--
Daniel Dias dos Santos
Java Developer
SouJava & JCP Member
Linkedin: http://br.linkedin.com/in/danieldiassantos


--
You received this message because you are subscribed to the Google Groups "MVC 1.0 Users Mailing List" group.
To unsubscribe from this group and stop receiving emails from it, send an email to jsr371-users...@googlegroups.com.
To post to this group, send email to jsr371...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/jsr371-users/588fe997-4b33-4347-ba70-d83bada70371%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Christian Kaltepoth

unread,
Jun 19, 2018, 4:20:26 PM6/19/18
to MVC 1.0 Users
Hi Ralph,

see my response inline.


I have a question about controllers and javax.enterprise.context.SessionScoped
This controller seems to work fine with Wildfly (RestEasy). It is instantiated once in a session. But running the same code in Payara/Glassfish (Jersey) the controller is created in each request - so it seems my annotation @SessionScoped is ignored? 
Is this normal, is this expected or am I doing something totally stupid here?

Actually we depend on the JAX-RS implementation for handling the controller lifecycle. The JAX-RS 2.1 spec states in 3.1.1 "Lifecycle and Environment":

By default a new resource class instance is created for each request to that resource. First the constructor (see Section 3.1.2) is called, then any requested dependencies are injected (see Section 3.2), then the appropriate
method (see Section 3.3) is invoked and finally the object is made available for garbage collection. An implementation MAY offer other resource class lifecycles, mechanisms for specifying these are outside the scope of this specification. E.g. an implementation based on an inversion-of-control framework may support all of the lifecycle options provided by that framework.

So supporting other lifecycles than per-request is actually optional as defined in the JAX-RS spec.

BTW: I don't think that session-scoped controllers make a lot of sense. MVC is very stateless by nature. So if you want to preserve some state, you should create separate session-scoped beans and then inject them into the request-scoped controllers. This should work fine. 

 
My application runs with javax.mvc-api 1.0-pr and ozark-resteasy 1.0.0-m03
....OK ...and now as I am writing this lines, it seems to be stupid... I think I have to use a ozark-jersey module here instead of ozark-resteasy?

Correct. :-)

 
But so I came to another question: In a situation, where I am building a general application to be deployed on wildfly or payara, do I need to create separate builds? Is this the correct way? I think I can do this with maven profiles....

Yes, unfortunately you currently need additional Maven artifacts depending on your JAX-RS implementation. That's because plain JAX-RS doesn't expose all the APIs the MVC RI needs.

 
And finally: I am absolutely fascinated how easy it is to build applications with MCV 1.0. I come from the JSF world and stared migrating form JSF to MVC. Once again: many thanks for this great framework!!

Thanks a lot! I also worked with JSF for about ~7 years. And I agree that MVC is much much simpler. However, of course JSF has many benefits too. Especially the data binding and validation lifecycle of JSF makes it very useful for form-based applications. MVC is just a completely different approach with other strength and weaknesses.

Christian


--

Ralpus

unread,
Jun 19, 2018, 5:13:59 PM6/19/18
to jsr371...@googlegroups.com
Hello Christian,

yes, sounds reasoned. 
The strange thing is, that I worked on my application the whole weekend with session scoped beans.
And those beans are no longer working now. 
I tried to remove all session scopes form my mvc controllers. But even if I try to inject a session scoped bean into a controller (which should work from your explanation)  this bean is now also  newly created on each request. 
This is a little bit insane that I can no longer work with CDI beans at all. And I swear, I haven't changed anything  ;-)

just to make it more clear, the following code snipped is ok? Or is it unreasonable in your eyes?

@Controller
@Path("teams")
@Named
public class TeamController extends DocumentController {

@Inject
MySessionBean mySessionBean;  // this bean is @SessionScope 
 ....
}

==
Ralph



--
You received this message because you are subscribed to the Google Groups "MVC 1.0 Users Mailing List" group.
To unsubscribe from this group and stop receiving emails from it, send an email to jsr371-users...@googlegroups.com.
To post to this group, send email to jsr371...@googlegroups.com.

Christian Kaltepoth

unread,
Jun 20, 2018, 1:39:59 AM6/20/18
to MVC 1.0 Users
Hmmm. That's weird. A few things that come to my mind:
  • Could you double check that you are using @javax.enterprise.SessionScoped and not the JSF annotation
  • Do you have a beans.xml with discovery-mode=auto or annotated?
  • You actually don't need the @Named annotation on the controller, try to remove this one.
I hope this helps.

Christian


For more options, visit https://groups.google.com/d/optout.

Ralpus

unread,
Jun 20, 2018, 3:12:09 AM6/20/18
to jsr371...@googlegroups.com
everything is working now. There were two thing hitting me:

1. I worked with payara (jersey) and wildfly (resteasey) in parallel during development. Not closing the browser leads to a wrong/deprecated JSESSIONID which is explaining the strange behavior in wildfly after switching back from payara. So there is no problem with mvc. It was 'normal' CDI/Webcontainer/Cookie stuff. 
2. In fact my application is working when I use a separate sessionscoped bean injected into the mvc controller classes. The session bean is working in the expected way (one instance per session)  and this is working in Jersey and Reasteasy. The strange thing was, that Wildfly also accepts JaxRS Beans annotated with @sessionScope. This is - as you explained - an unexpected behavior and was leading me on the wrong path. When a jax-rs bean is created per each request (as the spec states) than the annotation @sessionScope should at least print a warning. But this is a resteasy topic I think.

So thanks for you help.
But still I have a final question: You say that I can also leave the @named annotation . But now I lost the concept of MVC in total: My controller should do something - for example searching a collection of documents. These documents are typically a bean property of my controller. I want to display the result in my jsf/faces Page. But I notice, that now again in Payara when the page is rendered, the controller bean is created once again (??). In Wildfly the controller bean still exists (this is what I expect, because it is the same request). 
So my question is now: what is the correct way to provide my search result back to the rendering page? Did I need now one more separate CDI bean just to hold the data ?


My facelets page - accessing the search result - looks like this:

<ui:repeat var="record" value="#{queryController.documents}">
<tr>
<td><a
href="#{facesContext.externalContext.requestContextPath}/app/document/#{record.item['$uniqueid']}">#{record.item['$uniqueid']}</a></td>
<td>#{record.item['$created']}</td>
<td>#{record.item['$modified']}</td>
<td>#{record.item['$workflowstatus']}</td>
<td>#{record.item['txtworkflowsummary']}</td>
<td><a
href="#" onclick="deleteDocument('#{record.item['$uniqueid']}')"
title="#{record.item['$uniqueid']}">del</a></td>
</tr>
</ui:repeat>


===
Ralph









Ralpus

unread,
Jun 20, 2018, 3:18:12 AM6/20/18
to jsr371...@googlegroups.com
Just to complete my findings:
When I store my data in a separate CDI Bean annotated with @RequestScoped injected into my MVC Controller it works in payara also.

So a MVC controller should not be annotated as a CDI Bean (@named) at all??

Christian Kaltepoth

unread,
Jun 20, 2018, 4:55:44 AM6/20/18
to MVC 1.0 Users

Hi Ralph,

I think there is some misunderstanding regarding the role of the controller. In MVC the controller is responsible for:
  • Populating the model
  • Choosing the view to render
So the controller and the model (which holds the data to render) are two distinct things in MVC.

If you want to pass data from your controller to your view, you basically have two options:


javax.mvc.Models

You can inject a "Models" instance into your controller which is basically a map like data structure. If you store something in this map, you can access it in your view:

@Controller
@Path("books")
public class BooksController {

  @Inject
  private Models models;

  @GET
  public String get() {
    models.put( "books", Arrays.asList( "Book1", "Book2", ... ) );
    return "books.jsp;
  }

}

In your view:

<p>
  Number of books: ${books.size()}
</p>


CDI Models

CDI models are closer to what you most likely know from JSF. Basically there is some @Named CDI bean that holds the data required for the view in a "presentation model" like way. You can then inject this model into your controller and populate it as required. The view can then access the data like you would do it in JSF:

@Named
@ReqestScoped
public class BooksPage {

  private List<String> books = new ArrayList();

  // getter + setter

}

@Controller
@Path("books")
public class BooksController {

  @Inject
  private BooksPage booksPage;

  @GET
  public String get() {
    booksPage.setBooks( Arrays.asList("Book1", "Book2", ...) );
    return "books.jsp;
  }

}

<p>
  Number of books: ${booksPage.books.size()}
</p>


Please note that both approaches have strength and weaknesses. It depends on your particular situation which one works best. I for example usually prefer javax.mvc.Models for passing data which is very specific for an individual view. IMO this is the easiest way. And you don't pollute the global EL namespace with tons of presentation models like in JSF. However, there are also cases for which CDI models make more sense. Especially if you think of "global" data which you may need on multiple views. Just think of the requirement to render the name of the currently logged in user into the page header of each view. This is very easy to achieve with CDI models.

I hope this helps.

Christian



--
You received this message because you are subscribed to the Google Groups "MVC 1.0 Users Mailing List" group.
To unsubscribe from this group and stop receiving emails from it, send an email to jsr371-users...@googlegroups.com.
To post to this group, send email to jsr371...@googlegroups.com.

For more options, visit https://groups.google.com/d/optout.

Ralpus

unread,
Jun 20, 2018, 7:32:27 AM6/20/18
to jsr371...@googlegroups.com
Thanks for that clarification. I now change my controllers/model beans in my application and removed the @named annotation form the mvc controllers as you suggested. I am working with injected CDI models and everything works perfect. 

Why I was so confused: The problem comes from Wildfly. Wildfly and it's CDI implementation is very tolerant concerning scopes. You can nearly mixing all things together - servlets, Beans, EJBs, cdi-events... . Wildfly will always handle this. In contrast Glassfish is more strict in handling CDI and this can lead in a situation where an application, developed in Wildfly will break in Glassfish. This is a little bit frustrating. Because glassfish and payara are the main implementations of Java EE and in case of CDI and Jax-RS there is a lot of different behavior. For example in Wildfly the following code snipped is fine:

// javax.ws.rs.client.Client 
client.target(uri).request().put(null);

in Payara this code dose not work because the implementation complains about the missing Entity object. 

For most projects this is no problem at all because they are developed against only one specific platform. But if you try to implement a general framework (like your Imixs-Workflow project) it is hard work to avoid the usage of proprietary code and ensure that the code is interpreted in the same way on both platforms. 

But this is now a little bit off topic. So concerning my question everything is fine now. In MVC it is important to understand the Model concept as you explained again. 
Would it make sense to print a warning in case an MVC controller is annotated with @named?

===
Ralph


Christian Kaltepoth

unread,
Jun 20, 2018, 7:44:25 AM6/20/18
to MVC 1.0 Users
Hi

 
Thanks for that clarification. I now change my controllers/model beans in my application and removed the @named annotation form the mvc controllers as you suggested. I am working with injected CDI models and everything works perfect. 

Great to hear! 


Why I was so confused: The problem comes from Wildfly. Wildfly and it's CDI implementation is very tolerant concerning scopes. You can nearly mixing all things together - servlets, Beans, EJBs, cdi-events... . Wildfly will always handle this. In contrast Glassfish is more strict in handling CDI and this can lead in a situation where an application, developed in Wildfly will break in Glassfish. This is a little bit frustrating. Because glassfish and payara are the main implementations of Java EE and in case of CDI and Jax-RS there is a lot of different behavior.

The problem is that the integration between different specs (CDI + Servlet, etc) is always a bit difficult. There are many corner cases and if these aren't explicitly described in the spec, then it is up to the implementation. Also, these integrations required coordination between the different expert groups in the past. Let's hope that Jakarta EE can improve this.

 
For example in Wildfly the following code snipped is fine:

// javax.ws.rs.client.Client 
client.target(uri).request().put(null);

in Payara this code dose not work because the implementation complains about the missing Entity object. 

I strongly recommend bringing such topics up to the corresponding Jakarta EE API projects. It is very important to point these projects to such inconsistencies so that these can be fixed in the next version of the spec. In case of JAX-RS you can file an issue here:


I'm committer on the JAX-RS API project, so I can help with getting this resolved. :-)


For most projects this is no problem at all because they are developed against only one specific platform. But if you try to implement a general framework (like your Imixs-Workflow project) it is hard work to avoid the usage of proprietary code and ensure that the code is interpreted in the same way on both platforms. 

I agree. That's exactly the reason why there are different Ozark modules for Jersey and RESTEasy. There are inconsistencies between the different implementations and/or specific things can only be achieved in an implementation specific way.


But this is now a little bit off topic. So concerning my question everything is fine now. In MVC it is important to understand the Model concept as you explained again. 
Would it make sense to print a warning in case an MVC controller is annotated with @named?

Yeah, this could make sense. But this is something that should be addressed in the specific MVC implementation and doesn't really belong into the spec. But feel free to file an issue here:



Thanks

Christian
Reply all
Reply to author
Forward
0 new messages