Using http session in Stateless Session Bean via #Context - java

I have created a Web-Application that shows documents to the user.
The application uses RESTFUL Webservices to get this documents from the backend.
The EJB responsible for creating / loading the documents needs some information stored in the http session.
(There was a requirement to determine how long a document has been openend, how long loading took etc., there is data stored in the session to determine which document in which browser window was closed or updated)
My solutions to get this informations looks like this (in the SSB and an Interceptor for another SSB):
#Context
private HttpServletRequest request;
...
this.request.getSession().getAttribute(WINDOW_SET);
This solution is working.
I am not sure this is the "right way" to do it, since #Context is not really meant for use in an EJB as far as I researched until now.
I can not just pass the needed information to the EJB as an argument, since this would not work with the Interceptor used.
The question is:
Is this a valid way to build this functionality?
If not, what are the drawbacks of this solution and how could it be done better?

No. The bean is annotated as stateless: it must be stateless. You can't expect injection of the request or the session to even work.
What a 'stateless session bean' actually means is another question, and one which I've been pondering since about 1998.

Related

EJB : understanding how container choose bean

I'm trying to understand how statefull beans works (I read the theoretical part and I know the difference between statfull and statelss beans ...), for that reason I created a statefull bean and a rest API to access it.
I find out that the container create/instantiate a new bean for every request.
then I used a servlet to access the same statfull bean, and this time the container crate just one bean that serves all requests.
So my questions are :
why does the container create many bean for rest API ?? I know that it consider each request as a separate client but how it knows, since rest API or servlet are accessed using http requests??
why it consider request when it comes from servlet as one client?? (therefor it create one bean)
in my case (doing test localy) how to force the container to create more beans (how to simulate more than one client) when using servlet.
Thank you in advance
I checked the specs, but I could not find something about this. But that seems reasonable:
Somebody must take care about the SFSB instance, closing it when done.
When exposing an EJB business method of a SFSB as REST service, a generic servlet is used. The only scope available is the request scope of a single (stateless) HTTP call, so after the call is done, the generic servlet should close the SFSB.
The servlet has an explicit lifecycle. An injected EJB is create during initialisation of the servlet and can be closed on destroy.
You can lookup new SFSB instances with every HTTP session created, using the session context for subsequent calls on this session and closing the SFSB when the matching session is closed.

Is there a "Spring 3 MVC way" to listen to the end session event?

I would like to delete some temporal files when user session finishes. The information associated with the files is stored in an object annotated with #SessionAttributes.
The only way I've found to deal with this is creating an HttpSessionListener.
Is there a higher level, simplified, Springy way to listen to the session end event where I could easily get my annotated object?
You most likely will need to create a HttpSessionListener.
Another stackoverflow answer:
Detect session timeout in Spring 3/Spring Security 2.0.5
Also and example on how to load spring beans into it:
http://www.mkyong.com/spring/spring-how-to-do-dependency-injection-in-your-session-listener/
Two options to use HttpSessionListener with spring beans:
The first is to use WebApplicationContextUtils.getRequiredApplicationContext(servletContext) to obtain the servlet context. From there you have two sub-options:
use getBean(..)
If you want to use #Autowired / #Inject use getAutowireCapablyBeanFactory().autowireBean(this). You will have to do this only once (check if the fields are null), because the listener is singleton.
The second option is to use AspectJ and #Configurable on the listener.
Not directly related, but might be an interesting project to look at.
https://github.com/shawnmclean/Idle.js
Session deletion typically happens on the server side, when the session expires (usually 30mn). The project above allows to detect user behaviors in the front end.

Intercept calls to HttpSession in Tomcat 6

What's the recommended approach to intercepting session.getAttribute() and session.setAttribute()? This is in a Spring based application so something AOP-based would be great. I'd like to avoid having to override core Tomcat classes if possible.
Update: I want to store the actual serialized attributes in a web service.
I am not familiar with AOP or Spring (or Tomcat). :) But I am familliar with Java
The way I do it is set up a filter, and replace the request variable with my own object
request = new MyRequest(request);
Then override getSession() and getSession(boolean) to return an instance of MySession
the javax.servlet.HttpServletRequest and javax.servlet.HttpSession classes are Java EE standard and not Tomcat specific.
You could implement your own session org.apache.catalina.Manager and swap it into Tomcat's configuration, although the interface looks rather lengthy - so perhaps look at extending ManagerBase or StandardManager first.
As an alternative, register a HttpSessionAttributeListener to be notified whenever a session attribute is added/removed/updated. This won't change the default storage mechanism - the session data will still be kept in-memory as well - but it would let you persist the data with an alternative mechanism as well.

a spring bean to wrap salesforce web service calls

I am trying to figure out how to create a stateless spring bean that wraps a group of calls to salesforce web service API. My understanding is that the process for calling salesforce is something like this:
Call the login service to Log into salesforce
Make a series of service calls
Call the logout
To have a stateless wrapper it seems right pattern is to have each method in the bean perform all three steps above. e.g. (pseudocode)
binding.login();
binding.upsert(….);
binding.upsert(….);
binding.logout();
Is this a good practice? It seems it would be a costly way just to keep the bean stateless. Would it be preferable in this instance to make the bean request scope?
I agree with Anup, you should take a look at the sfdc wsc.
If you want go entirely stateless you will need to know the following things about a salesforce connection.
every action must have an endpoint url, something like na6.salesforce.com or na7.salesforce.com
every action must have a valid SID(session id) for the action to complete.
When you login to salesforce the original endpoint is login.salesforce.com and if you are sucessfull you will be returned a valid endpoint(na6.salesforce.com) and a SID.
You can then drop that endpoint/sid into a singleton and share it with as many spring beans as you want. In each bean you will need to create a new SoapBindingStub and set the endpoint and sid before you execute an insert/upsert/update/etc. action.
That sid will expire after a period of inactivity (anywhere from 30-120 minutes depending upon setting) so you should catch any exceptions and relogin using the singleton object.
Dont worry about two beans casuing the singleton relogin at the same time because salesforce will return the sames sid to both.
Have you tried SFDC WSC library? It's easy to use, and fits the use case that you are trying to accomplish.

Best way to show the user full name in a JSP header file with a spring/struts framework?

I have a JSP struts application that uses Spring to integrate with the services/dao/database. Basically, struts uses spring to get the data from the DB, it builds the form and forward them to the JSP files.
I have a header file that is injected in each JSP file using Tiles. I would like to show "Welcome John Doe" on each page inside the header. Where "John Doe" is the name of the currently logged user.
What would be the best approach to do that? The solution that I can think of is:
Use a Spring Filter the catch the http request. Load the user from the database using a cookie that contains the user id(*) and put the name in a session bean named "CurrentUser"
In "header.jsp", get the spring application context. Using it, load the bean "CurrentUser" and get the name. Put the name in the html.
I think I could get this to work. But I'm not certain this is the best way to do it. Any thought on my approach?
(*) Of course, the cookie will be encrypted
Although it may be an extremely large hammer for your fairly simple use-case, we have gotten a really neat spring-jsp integration (jsp 2.1 required!) by using ELResolver. By following this tutorial you can basically inject any spring managed bean into your el-context and allow it to be accessed using jsp-el like this:
${spring.mybean.myproperty}
You can choose to inject pre-defined beans into your el-context or simply pass "mybean" to getBean and allow almost anything spring-managed to be accessible from jsp. mybean could easily be a session-scoped spring bean.
I'm not totally sure how this would align with tiles, though.
Are you not already storing some sort of User object in Session?
If so, I would just add a "getFullName()" method to this domain object and have the DAO populate it when it returns it. Ideally you should populate the User object when the user logs in, store it in session, and not need to load all of the user's details again from the database on each and every page request.
(Are you not using Spring Security? If so, they provide a pretty simple way to store a UserDetails-like object in Session, and easy access to it.)
I'd vote against both of your approaches because
This means (at least) an extra database call per page request
This wouldn't work if other users shared the same bean in the same context. Also, you really shouldn't have JSP files (which are your presentation layer) interacting with data services directly.

Categories

Resources