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/[email protected]".
User B request => "http://domain.com/users/[email protected]".
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.