Background
The Apache Action class is not thread-safe. However, this was only realized after implementing a base class, upon which all other classes in the system depend. The base class uses a number of instance variables:
private HttpServletRequest request;
private ArrayList inputParams = new ArrayList();
private Connection connection;
private String outputParameter;
private boolean exportEnabled;
Fortunately, all usages of those variables are accomplished through accessor methods, exclusively. For example:
public boolean getExportEnabled() {
return this.exportEnabled;
}
public void setExportEnabled( boolean exportEnabled ) {
this.exportEnabled = exportEnabled;
}
Problem
The base class is running in a multi-threaded Servlet environment.
Solution #1
To resolve this issue, I was thinking about using a HashMap keyed to the session. However, this would require re-writing all of the methods, and dependent code:
private static HashMap sessionVariables = new HashMap();
public boolean getExportEnabled( HttpSession session ) {
return getSessionVariables().get( session.getId() + '.exportEnabled' );
}
public void setExportEnabled( boolean exportEnabled, HttpSession session ) {
getSessionVariables().put( session.getId() + '.exportEnabled', exportEnabled );
}
That is a lot of work, and would likely introduce bugs.
Solution #2
It might be possible to change the base class to an "empty" class. This empty class would have a single method:
public ActionForward execute(
ActionMapping mapping,
ActionForm form,
HttpServletRequest request,
HttpServletResponse response )
throws Exception {
// Instantiate "this" and forward the request?
}
But it would have to know the appropriate base class to instantiate, or perhaps instantiate a new version of itself to handle the call.
Update #1
I believe the Struts architecture does the following:
Create an instance of the Action subclass.
Re-use that same instance for every request.
Obtain a thread (from a thread pool) when receiving a new connection.
Call execute on the Action subclass from the thread.
Handle multiple new connections using different threads.
The same execute method will be called on the same instance of the object, resulting in unsafe behaviour because the subclass has instance variables.
Update #2
The following solution seems to solve the issue:
public ActionForward execute(
ActionMapping mapping,
ActionForm form,
HttpServletRequest request,
HttpServletResponse response ) throws Exception {
((MyClass)clone()).executeClone( mapping, form, request, response );
}
public ActionForward executeClone(
ActionMapping mapping,
ActionForm form,
HttpServletRequest request,
HttpServletResponse response ) throws Exception {
// Former "execute" method code goes here.
// ...
}
The original execute method was renamed to executeClone. The new execute implementation creates a clone of the current class and subsequently calls executeClone. This minimally invasive technique avoids introducing new bugs while making the class thread-safe.
Question
What would be the most reliable way to make the code thread-safe while minimizing the risk of introducing bugs?
Thank you!
Solution #1 is dangerous because it assumes that the session is thread-safe, which is not necessarily the case. Someone could be making two simultaneous requests with the same session.
Solution #2 could be easily implemented by making your base class implement Cloneable. Then it can clone itself, set the clone's instance variables, and then call super.execute(). If you think it's too hard to change the design to make your base class be properly thread-safe, this might be an easy way out.
What would be the most reliable way to make the code thread-safe while minimizing the risk of introducing bugs?
There is no general answer to this. What you need to do to make a class thread-safe depends on what the class does, its API design ... and what level of thread-safety you require. In some cases, it is not even practical to make something thread-safe; e.g. read the javadoc for Collections.synchonizedList and look about how it handles the iterator() method.
Related
Recently I came across with a builder pattern that intrigued me.
So, I have an EntityBuilder which builds an Entity, but it doesn't return the entity. Here is the method signature:
public void build();
Instead, inside the build() method, it delivers the new object created, the Entity, to a CacheImplementation instance to store it.
Note: the CacheImpl is injected in the builder's constructor.
public void build(){
//create new entity
cacheImplementation.add(entity);
}
Does this sounds like best practice?
Later edit 0
public interface EntityBuilder {
void setProperty0(PropertyObject propertyObject0);
void setProperty1(PropertyObject propertyObject1);
void setProperty2(PropertyObject propertyObject2);
//...
void build();
}
public class EntityBuilderImpl implements EntityBuilder {
PropertyObject propertyObject0;
PropertyObject propertyObject1;
PropertyObject propertyObject2;
//...
// setters for all properties
#Override
public void build(){
//create new entity
cacheImplementation.add(entity);
}
}
The builder is used in the following way:
public class EntityProcessor{
private EntityBuilderFactory entityBuilderFactory;//initialized in constructor
void process(EntityDetails entityDetails){
EntityBuilder entityBuilder = this.entityBuilderFactory.getNewEntitytBuilder();
//..
// entityBuilder.set all properties from entityDetails
entityBuilder.build();
}
}
Note: the cacheImpl instance just stores the entities in a List<> which is accesses every N seconds.
Does this sounds like best practice?
The traditional builder pattern doesn't store the created object anywhere, it simply returns it.
I can imagine a variation where the builder also has a role of instance control to avoid creating duplicate objects, and managing a store of immutable objects.
The decision to not return an instance could be to make it clear that the method has a side effect. If the method returned the object, it might mislead to thinking that it's a traditional builder without side effects, when that's not the case here.
In any case, all this is just speculation, as we haven't seen the rest of the code where this is used and the way it is implemented and used. We don't have enough context to really judge.
There's nothing wrong with inventing new patterns, but it can be done well or badly.
I've seen similar void build() method in the JCodeModel class. As you can see it throws IOException because of the resources it manages:
public void build(File destDir,
PrintStream status)
throws IOException
You basically ask it to carry out the operation for you and if no error is present - you can continue with the workflow.
In general builder is used in following way:
Some class will use builder to create class. Simple
Now you have additional piece of complexity - caching. You can put caching inside Builder or one level higher inside Processor.
What are the implications of putting cache management inside builder:
Builder does not have single responsibility anymore.
It does not work how you would expect at first glance
You are unable to create object without putting it into cache
These problems will not occur if you put cache management to separate class.
I would say that it is not terrible solution, but it certainly will decrease maintainability of your code.
I have a RemoteServiceServlet class implements several services (methods).
All the methods need to check the session and get the corresponding user info before doing anything. Since the class have more than 20 service methods, doing so in every service is a nightmare. Is there a way to run some session checking method automatically for all the incoming requests? Or how can I solve this problem?
Here is an example pseudo-code for my situation.
public class OnboardingServiceImpl extends RemoteServiceServlet implements OnboardingService {
private String checkSessionAndGetUser(){...}
public void service1(){
// check session
// get user and do something based on the user data
}
public void service2(){
// check session
// get user and do something based on the user data
}
public void service3(){
// check session
// get user and do something based on the user data
}
...
public void service20(){
// check session
// get user and do something based on the user data
}
}
As you can see, service1, service2, ..., service 20 all need to get the user info based on the session, but I do not want to repeat writing the code for every service. Any help will be appreciated.
I'd suggest to override processCall(RPCRequest rpcRequest)
#Override
public String processCall(RPCRequest rpcRequest) throws SerializationException {
//your checks here, in case of error:
//return RPC.encodeResponseForFailedRequest(null, new Exception("Invalid session"));
// note that you'll have to use a serializable exception type here.
return super.processCall(rpcRequest);
}
RemoteServletServlet's doPost is final, but not service, so you can put your code there.
…or use a servlet filter.
This will however be done outside the "RPC" (before the request is even decoded), so response cannot just be a "throw exception and have it passed to onFailure on client side".
For that, you'll have to either use aspect-oriented programming (such as AspectJ) to "inject" code into all your methods, or call an init method at the beginning of each method (you'll keep repeating the code, but that could possibly be reduced to a one-liner).
I'm using a custom interceptor which creates a new db connection, and sets this connection onto the current action before executing the action. After that, the interceptor closes the connection.
I'm looking for a convenient way to share this db connection with other classes / static methods (such as Models) that are used by the action. E.g so I can call static method like User.get( id ) or User.getEmail( id ) without having to pass the db connection to each method separately.
I could set the db connection onto the ActionContext from the interceptor, by doing:
ServletActionContext.getActionContext().put("db", db );
And then I could access this db connection from a static method, such as:
public class User implements Model
{
public static String getEmail(int id)
{
Connection db =
(Connection) ServletActionContext.getActionContext().get("db");
//...
}
}
My question is, would a new ActionContext be generated for every given request, so I can be sure that a new db connection will be used each time? E.g if I have 500 people visiting mysite.com/fooAction, could I be sure that each of those 500 requests is generating a unique ActionContext, and each call to User.getEmail() would access only the db connection which is unique to the given request?
Thanks.
To answer the question :
My question is, would a new ActionContext be generated for every given
request, so I can be sure that a new db connection will be used each
time?
Is yes. Reference is the java-doc. It similar to the one provided by Alfredo Osorio only it refers to 2.3.x version.
Can you say what struts2 version is being used?
I was not able to find any version that uses
ServletActionContext.getActionContext()
but instead the signature is
ServletActionContext.getActionContext(javax.servlet.http.HttpServletRequest)
To answer the comment regarding thread-local being static and still the ActionContext instance being unique per request its because the doing a
ActionContext.getContext()
internally invokes a get on the thread local instance.
actionContext.get()
You may find the following post helpful in this regard.
However to delve deeper, the method
ServletActionContext.getActionContext(javax.servlet.http.HttpServletRequest)
takes a different route than using the thread-local.
public static ActionContext getActionContext(HttpServletRequest req) {
ValueStack vs = getValueStack(req);
if (vs != null) {
return new ActionContext(vs.getContext());
} else {
return null;
}
}
public static ValueStack getValueStack(HttpServletRequest req) {
return (ValueStack) req.getAttribute(STRUTS_VALUESTACK_KEY);
}
getActionContext
getValueStack
Below are some additional references (source code).
ValueStack
OgnlValueStack
ActionContext
The following posts may also be helpful.
will-a-new-actioncontext-and-valuestack-be-created-for-every-new-action-object
struts2-actioncontext-and-valuestack
Update 2 :
Wanted to add as mentioned here (Link 1 above) that in case of ActionChaining being involved, the action is invoked with its own interceptor stack and result.
The thread in which its executed, however is the same.
The value-stack and parameters are copied over. See - ActionChainResult#execute(ActionInvocation).
Once the chain-invocation is complete, the state of the action-context is reset. (See DefaultActionProxy#execute() ).
Partial Information : Although the action-invocation is set in DefaultActionInvocation#init(ActionProxy) I was not able to determine if or where it is reset.
Sources :
DefaultActionInvocation
DefaultActionProxy
DefaultActionProxyFactory
ActionChainResult
FilterDispatcher(Deprecated)
My question is, would a new ActionContext be generated for every given
request, so I can be sure that a new db connection will be used each
time?
Since ActionContext uses ThreadLocal it is thread safe. Struts 2 creates an ActionContext for each request, and each request has its own thread. So yes, if you create a new connection and store it in the ActionContext every thread will have its own connection. But I don't recommend you to store the connection in the ActionContext because this couple you to Struts 2 which is not a good thing, also your services shouldn't be calling web specific classes because it also couple them.
From Struts 2 Javadoc:
The ActionContext is the context in which an Action is executed. Each
context is basically a container of objects an action needs for
execution like the session, parameters, locale, etc.
The ActionContext is thread local which means that values stored in
the ActionContext are unique per thread. See the
ActionContext.ActionContextThreadLocal class for more information. The
benefit of this is you don't need to worry about a user specific
action context, you just get it:
ActionContext context = ActionContext.getContext(); Finally, because
of the thread local usage you don't need to worry about making your
actions thread safe.
ActionContext excerpt:
public class ActionContext implements Serializable {
static ThreadLocal<ActionContext> actionContext = new ThreadLocal<ActionContext>();
....
}
I've seen the builder pattern recommended in a variety of places, but wasn't sure on thread safety within a Web application using Struts.
I am unclear as to whether the variables of the build static method are shared by, or internal to each thread that invokes the builder code. I have a hunch it's okay, but want to be sure given that the builder code lives inside a Web application and could be invoked by 10s of threads at once.
public static class ExampleBuilder {
public static Thing build(ActionForm form) {
String property1 = form.property1;
String property2 = form.property2;
String propertyX = form.propertyX;
...
return new Thing(property1, ...);
}
}
public class ExampleStrutsAction extends Action {
public ActionForward execute(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException {
Thing example = ExampleBuilder.build(form)
return mapping.findForward("success");
}
}
The above build() method only uses local variables, and doesn't access any state that is shared between threads, so it's thread-safe. Local variables are local to each method invocation, and are thus not shared between threads.
The only thread-safety problem you could have is if the form has the scope session (which is a bad practice). In this case, two threads could use the same ActionForm instances. But this is not really a problem of the build() method. Rather a design problem, or a synchronization problem of the execute() method(s) that use this session-scoped ActionForm.
After the code modifications you did I can say that your code is thread-safe anyway because you do not use any member variables into build() method. You can invoke as build() simultaneously from several threads and each thread will use its own method-level variables.
BTW making this class static does not have any sense here. Static modifier in class context is relevant for inner classes only. Inner static class does not have access to instance of outer class. Top level class does not have outer class at all, so it cannot access its instance anyway.
I have a servlet that invokes generic actions passing in a form and object (depending on what the action needs)
CommitmentServlet.java
CommitmentListDAO clDAO = new CommitmentListDAO();
CommitmentItemForm form = new CommitmentItemForm(clDAO);
CommitmentItem obj = new CommitmentItem();
actionMap.put(null, new ListAction(form);
actionMap.put("list", new ListAction(form);
actionMap.put("view", new ViewAction(form, obj)
actionMap.put("delete", new DeleteAction(form, obj);
actionMap.put("edit", new EditAction(form, obj);
ControllerAction action = (ControllerAction) actionMap.get(request.getParameter("method"));
action.service(request, response);
EditAction.java
public class EditAction implements ControllerAction {
private Form form;
private Object obj;
public EditAction(Form form, Object obj) {
this.form = form;
this.obj = obj;
}
public void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
obj = form.edit(request);
request.setAttribute("obj", obj);
request.setAttribute("form", form);
if (form.isSucces()) {
RequestDispatcher view = request.getRequestDispatcher(success page);
view.forward(request, response);
}
else {
RequestDispatcher view = request.getRequestDispatcher(failure page);
view.forward(request, response);
}
}
}
The actual business logic is located in the form object passed in to the generic action.
The generic actions allow me to quickly get CRUD Controller functionality for any new objects. I just have to code the business logic form such as here
CommitmentItemForm.java
public Object edit(HttpServletRequest request) {
CommitmentItem commitmentItem = null;
STKUser authenticatedUser = (STKUser) request.getSession().getAttribute("STKUserSession");
String ownedByBadge = null;
List deptSupervisorList = null;
try {
deptSupervisorList = STKUserDAO.getList(authenticatedUser.getDepartment()); //<--- Static call is it OK??
commitmentItem = CommitmentListDAO.retreive(request.getParameter("commitment_id"), authenticatedUser);
ownedByBadge = commitmentItem.getOwned_by();
}
catch (DAOException e) {
setError(FORM_RESULTS, e.getMessage());
}
catch (ValidatorException e) {
// ValidatorExceptions are thrown when the DAO can not find a record
setError(FORM_RESULTS, e.getMessage());
LOGGER.log(Level.INFO, e.getMessage(), authenticatedUser);
}
if (ownedByBadge != null) {
if (ownedByBadge.equals(authenticatedUser.getBadge()) || ownedByBadge.equals(authenticatedUser.getAtaBadge())) {
}
else {
setError(FORM_RESULTS, "You are not authorized to edit this data.");
LOGGER.log(Level.INFO, "Error - You are not authorized to edit this data '" + commitmentItem.getCommitment_id() + "'", authenticatedUser);
}
}
request.setAttribute("deptSupervisorList", deptSupervisorList); // <--- Is this acceptable to do???
return commitmentItem;
}
1) is my approach of setting a request attribute and returning an object in method un orthodox?
2) I'm making a static call to get the deptSupervisorList. Is this asking for trouble??
3) Does my servlet, generic action, business form seem like an acceptable approach to develop a java web application without using a framework?
EDIT:
What is the difference?
Static
deptSupervisorList = STKUserDAO.getList(authenticatedUser.getDepartment());
vs
non-static
STKUserDAO userDAO = new STKUserDAO();
deptSupervisorList = userDAO.getList(authenticatedUser.getDepartment());
public static List getList(String dept) throws DAOException {
...
}
First some caveats:
This is subjective
I agree with SidCool that the answer is to take a look at some of the existing web application frameworks out there. If anything, just to find out how they do it.
I'm a massive fan of dependency injection
To answer your questions:
It's not great to pass data around in request attributes because: it's not type safe; it's a bit of an invisible bag of things -- always better if you can see output objects in the type signature; at some point you'll find yourself wanting to store two things in the request attributes under the same name
Dependency injection is the way of the future. Making a static call is bad because: you've now tightly coupled the two objects making reuse harder as well as making it harder to test
I'd definitely have a look at some other frameworks here. Most of them tend to have a single dispatch servlet, I think you'll end up writing a lot of very similar looking servlets. A lot of frameworks will also use reflection to try and get the transformation between request and POJO done as early and as easily as possible.
Other:
All of your actions are off parameters i.e. ?method=[list,view,delete,edit]. Often it is preferable to use routes (e.g. index.html is usually used for 'list').
To answer your feedback / questions from the comments:
Running on older version of Java
Wow, that sucks. There are frameworks that run on Java 1.4, though. Spring MVC would be my recommendation but there are more here. That said, the reason that I suggested looking at other frameworks wasn't just to use them but more to be inspired by them. Writing your own Web Application Framework is practically a rite of passage and can be pretty fun. Writing it in such a constrained environment just adds to the challenge.
What I'd suggest:
Try out a recent Java framework or even a non Java one (e.g. Ruby on Rails), just to see what's possible
When writing your own only framework, just use 1 servlet and dispatch down to your various 'controllers'. The reason for this is that Servlets are not great at letting you put your whole application together (what Spring MVC does, is loads up the 'application' using a ContextListener and then servlets and filters look up the 'application' from the ServletContext)
The tight coupling of static
Tight coupling is when two objects can't be used without each other, ever. Why is this bad, you ask? Because you can never reuse the code for something else (say, if you decided to load some data from a file, introduced a caching layer, used it in a different project etc.). Most importantly, some would say, is that it is difficult to test it. This is because you can't just replace the object that you statically call with another one. Interfaces are usually used to decouple objects but realistically, you can do it just by setting the object in via dependency injection (which is a complicated way of saying: put it in the constructor or as a setter).
OO and being a civil engineer
It's all good. Some of the best programmers I know didn't start out that way. For me, using the Dependency Injection pattern is an awesome way to write 'good' code by default. Note: if you look at Dependency Injection, you don't need a framework for it. You just need to construct all of your objects in one place and all of your objects should get all of their dependencies either in the constructor or in a setter. Not static methods or singletons allowed.
What's the difference
An alternative 'what's the difference' that better illustrates what I mean would look like this:
// code in your application builder
// assuming an interface called UserDAO
UserDAO userDAO = new STKUserDAO();
CommitmentItemForm form = new CommitmentItemForm(userDao);
public class CommitmentItemForm {
private final UserDAO userDao;
public CommitmentItemForm(UserDAO userDao) { this.userDao = userDao; }
public Object edit(HttpServletRequest request) {
...
deptSupervisorList = userDao.getList(authenticatedUser.getDepartment());
...
}
}
vs
public class CommitmentItemForm {
public CommitmentItemForm()
public Object edit(HttpServletRequest request) {
...
deptSupervisorList = STKUserDAO.getList(authenticatedUser.getDepartment());
...
}
}
The static method definitely looks like it's less work, so why is it so bad? Essentially, it's because in the static version, you can never look up the deptSupervisorList from anything but an STKUserDAO. In the non static version, you can supply any implementation of the UserDAO interface. This means that you could use the same CommitmentItemForm code regardless of whether:
You were doing it in a test and you were creating a Mock version of UserDAO that returned an exception every time so that you could test that
You found out that you needed to retrieve your departments list from a JSON HTTP REST web service, or from a file
It's also immediately obvious from the signature of CommitmentItemForm that it needs a UserDAO to function (because it's required in the constructor).
This is one of those little things that if you do it with all of your code, you will find that your code is not only more flexible, it's more testable, more reusable and the parts that you suddenly find you need to change in the future are better isolated.