Java – Spring MVC 3 for @Autowired Singleton Thread-Safety

google-app-enginejavasingletonspring-mvcthread-safety

Well, I have 3 layers from Controller->Service->Repository made in MVC Spring 3 design. Now, my question is, since the default scope is defined as Singleton, are they thread-safe?

Here is the code look like:

UserController.java

@Controller
@RequestMapping("/users")
public class UserController extends ExceptionExtension {
     @Autowired
     private IUserService userService;

     @RequestMapping(value = { "/update", "/update/" }, method = RequestMethod.GET)
     public String updateUser(@RequestParam("email") String eMail, ModelMap model)
        throws Exception {

          if (eMail.isEmpty() || eMail == null) {
              throw new ArgumentIsEmptyException("Required String parameter 'email' is empty");
          } else {
              UserModel userModel = userService.setUser(eMail);

              if (userModel != null) {
                  model.put("roleList", userService.setRoleList());
                  model.put("title", "Update Existing User");
                  model.put("post", "/users/post/update");
                  model.put("userForm", userModel);

                  return "users.update";
              } else {
                  model.put("title", "Update Existing User");
                  model.put("result", "<font color='red'><u>" + eMail + "</u> does not exist in the database.</font>");
                  model.put("flag", "Error");

                  return "users.result";
              }
          }
     }
}

UserService.java

public class UserService implements IUserService {

    @Autowired
    private IUserManager userManager;

    public UserModel setUser(String eMail) {
        UserModel userModel = new UserModel();
        Entity userEntity = userManager.getUser(eMail);

        if (userEntity != null) {
            userModel.setEMail(eMail);
            userModel.setRole(userEntity.getProperty("role").toString());
            userModel.setEnable((Boolean)userEntity.getProperty("enable"));

            return userModel;
        } else {
            return null;
        }
    }
}

Say, User A and User B are concurrently running the same url but different parameter.

User A request => "http://domain.com/users/update?user=myname1@domain.com".
User B request => "http://domain.com/users/update?user=myname2@domain.com".

Since the Controller is singleton, will the User A eMail variable overlaps to the User B one and the vice versa?

I am finding hard to understand on how is the Singleton Thread-Safe working in this scenario. Should my @Service and @Repository declare as @Scope("prototype) so the inner method variables are isolated from new instantiate?

====>

with Scope("request") to my @Service layer, I hitted this error message :/

3328 [main] ERROR org.springframework.web.context.ContextLoader –
Context initialization failed
org.springframework.beans.factory.BeanCreationException: Error
creating bean with name 'roleController': Injection of autowired
dependencies failed; nested exception is
org.springframework.beans.factory.BeanCreationException: Could not
autowire field: private com.company.dashboard.service.IRoleService
com.company.dashboard.controller.RoleController.roleService; nested
exception is org.springframework.beans.factory.BeanCreationException:
Error creating bean with name 'roleService': Scope 'request' is not
active for the current thread; consider defining a scoped proxy for
this bean if you intend to refer to it from a singleton; nested
exception is java.lang.IllegalStateException: No thread-bound request
found: Are you referring to request attributes outside of an actual
web request, or processing a request outside of the originally
receiving thread? If you are actually operating within a web request
and still receive this message, your code is probably running outside
of DispatcherServlet/DispatcherPortlet: In this case, use
RequestContextListener or RequestContextFilter to expose the current
request.

Best Answer

Here Thread Safety depends upon the internal locking of userService in case of scope singleton

This is what ultimately happens => The same userSpace bean is used for both the requests and both requests concurrently access userService bean. So the IUserService needs to be thread safe for the whole operation to perform well.

Or

put the scope to request.

In which case a new bean is allocated for every request and the whole operation is thread-safe, thanks to thread confinement. Provided you code accordingly in IUserSpace

Related Topic