• Post Reply Bookmark Topic Watch Topic
  • New Topic
programming forums Java Mobile Certification Databases Caching Books Engineering Micro Controllers OS Languages Paradigms IDEs Build Tools Frameworks Application Servers Open Source This Site Careers Other Pie Elite all forums
this forum made possible by our volunteer staff, including ...
Marshals:
  • Campbell Ritchie
  • Jeanne Boyarsky
  • Ron McLeod
  • Paul Clapham
  • Liutauras Vilda
Sheriffs:
  • paul wheaton
  • Rob Spoor
  • Devaka Cooray
Saloon Keepers:
  • Stephan van Hulst
  • Tim Holloway
  • Carey Brown
  • Frits Walraven
  • Tim Moores
Bartenders:
  • Mikalai Zaikin

Struts2 ModelDriven Not Threadsafe?

 
Greenhorn
Posts: 20
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Hello,

I'm working with struts2, hibernate and spring and using model driven pattern. It seems that there is a serious issue when trying to fetch an object with 2 different users and sessions (also different computers) at the same time exactly.

More info...
Let's say we have a Project object which has 2 members - user and name.
Both users will try to fetch their Project object (which is a different object for different user of course). So User A would have a project with id 498 and User B would have a project with ID 499.

The struts action would recognize that they're trying to fetch an object with different ID but it seems that both of the users have the same Project object instance and therefore they see the same result.
You could see in the log provided here:


2011-12-08 14:07:21 LoginInterceptor [INFO] User 17 is invoking populateProject, params: id=499
2011-12-08 14:07:21 LoginInterceptor [INFO] User 4 is invoking populateProject, params: id=498
2011-12-08 14:07:21 ProjectAction [INFO] Obj: hbn.Project@e2df60d, Session User Id is 17, obj.user.id is 4
2011-12-08 14:07:21 ProjectAction [INFO] Obj: hbn.Project@e2df60d, Session User Id is 4, obj.user.id is 4

How could I solve it?

Thanks,
Ron.
 
Ranch Hand
Posts: 485
Eclipse IDE Firefox Browser Linux
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Post your code how you implemented it.
 
Ron Zavner
Greenhorn
Posts: 20
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Hi,

This is the getter:

public Project getObj() {
logger.info("Obj: " + obj + ", Session User Id is " + getUser().getId() + ", obj.user.id is " + obj.getUser().getId());
return obj;
}

The fetching part is doing some business logic but the main part would be:
obj = dao.read(isLazy, allCrits);

Where obj is defined as a data member of the action with the type of the ModelDriven.
 
Bartender
Posts: 9626
16
Mac OS X Linux Windows
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
You haven't given us much to work on. Have a look at this article from our FAQ on how to describe a problem. The better question you ask, the more help we can be.
 
Ron Zavner
Greenhorn
Posts: 20
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Hi

Sorry bout that, will try to be more clear.

This is how the action starts:

public class ProjectAction extends GenericAction<Project> implements ModelDriven<Project> {

@Autowired
private WebsiteDAO websiteDAO;

@Autowired
private ProjectManagerDAO projectManagerDAO;

private Project obj;

public String populate() throws DataAccessException {
String myId = getRequest().getParameter("id");
if (myId != null && !myId.equals("")) {
logger.info("Fetching Project with Id " + id + " of user " + getUser().getId());
obj = (Project) dao.read(Integer.parseInt(myId));
logger.info("After fetch Obj: " + obj + ", Session User Id is " + getUser().getId() + ", obj.user.id is " + obj.getUser().getId());
}
return "form";
}

public Project getObj() {
logger.info("In getObj() Obj: " + obj + ", Session User Id is " + getUser().getId() + ", obj.user.id is " + obj.getUser().getId());
return obj;
}
....
}

In the UI I call populateProject?id=... from 2 different sessions at the same time and then the correct object is being fetched. Then in the jsp there is a form which has the follwoing line
<s:textfield name="name" key="Name" size="30" value="%{obj.name}"/>

This line is probably call the getObj function which for some reason access the same obj instance (for the different users).

That's the log file:

As you can see - the correct object was fetched and also saved to different obj instance. Problem started in the getObj method - last 2 lines of log.

2011-12-08 15:17:48 ProjectAction [INFO] Fetching Project with Id 498 of user 4
2011-12-08 15:17:48 ProjectAction [INFO] Fetching Project with Id 499 of user 17
2011-12-08 15:17:48 ProjectAction [INFO] After fetch Obj: hbn.Project@6c461f7c, Session User Id is 4, obj.user.id is 4
2011-12-08 15:17:48 ProjectAction [INFO] After fetch Obj: hbn.Project@3fa419d, Session User Id is 17, obj.user.id is 17
2011-12-08 15:17:48 ProjectAction [INFO] In getObj() Obj: hbn.Project@3fa419d, Session User Id is 17, obj.user.id is 17
2011-12-08 15:17:48 ProjectAction [INFO] In getObj() Obj: hbn.Project@3fa419d, Session User Id is 4, obj.user.id is 17

Thanks a lot.
 
Joe Ess
Bartender
Posts: 9626
16
Mac OS X Linux Windows
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

A Struts 2 Action instance is created for every request and do not need to be thread-safe. Conversely, Interceptors are shared between requests and must be thread-safe.


Struts 2 Guide: Writing Interceptors
 
Ron Zavner
Greenhorn
Posts: 20
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
I know...but as you can see the getObj method is part of the function so has to be thread-safe...but you can see from the code and log the obj was not thread safe so the problem still remains...
 
Joe Ess
Bartender
Posts: 9626
16
Mac OS X Linux Windows
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
You cannot use instance-scope variables like the way you have obj declared in thread-safe code.
 
Ron Zavner
Greenhorn
Posts: 20
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
So how should I use it?
In the tutorials of Model Driven I've seen that they declare the object as a data member of the action...it's exactly what i did.
 
Joe Ess
Bartender
Posts: 9626
16
Mac OS X Linux Windows
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
I'm sorry. I got confused and thought you were writing an interceptor. The interceptor has to be thread safe. The action does not, so the code you posted looks fine.
Are you certain that the code you posted is the code you are running? If you declared obj to be static, you'd see the behavior you are witnessing.
 
Ron Zavner
Greenhorn
Posts: 20
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Yes I'm sure, I re wrote the code (and tested it) so i could post something that would be clear

Maybe it has to do with struts-spring plugin? Since spring is initiating the struts actions...

Spring conf:
<bean id="projectAction" class="actions.ProjectAction">
<property name="dao" ref="projectDAO" />
</bean>
<bean id="projectDAO" class="hbn.dao.ProjectDAO">
<property name="sessionFactory" ref="sessionFactory" />
</bean>

Struts.xml

<action name="*Project" method="{1}" class="projectAction">
<result name="form">jsp/Project/form.jsp</result>
<result name="list">jsp/Project/list.jsp</result>
<result name="details">jsp/Project/details.jsp</result>
<result name="showReport">jsp/Project/showReport.jsp</result>
</action>

Thanks.

 
Ron Zavner
Greenhorn
Posts: 20
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
The problem is solved.

The issue was indeed due to struts and spring integration - the scope wasn't defined so default scope singelton was used.
After changing the action definition to the following it's working great

<bean id="projectAction" class="actions.ProjectAction" scope="prototype">
<property name="dao" ref="projectDAO" />
</bean>

Thanks.
 
Consider Paul's rocket mass heater.
reply
    Bookmark Topic Watch Topic
  • New Topic