Spring Singleton bean management - spring

There is scenario where we have 50 browsers opened accessing the application , if there is a singleton scoped(meaning one bean per container), then how the singleton bean is shared among all the instance of threads
or if one object is shared to only one browser(client) then all other client will be idle waiting which is bad design
Could some body suggest answer

For stateless beans, having a single instance ("singleton") is fine:
#Component
public class MyManager {
public void doStuff();
}
Any number of clients (browsers) can call doStuff() without impacting each other as long as doStuff() doesn't manage state.
For stateful beans that manage user state, you can use session scoped beans:
#SessionScope
#Component
public class UserPreferences {
private String username;
public setUsername(String username) {
this.username = username;
}
//...
}
The UserPreferences bean is instantiated once per HTTP session. Hence every client (browser) gets its own object.
In both cases one client (browser) does not have to wait until processing has finished for other clients.

Related

How to configure spring-ioc dependency Injection in a personal way?

I'm currently working on a web application using Angular 7 for front-end, spring-boot for back-end (in which I'm developing a restful web service).
I'm using #Autowired annotation to inject my services into each other and my rest controller. The problem is that in some of my services, there are some attributes that get shared when the injection is done. How do I prevent that?
import org.springframework.stereotype.Service;
import org.springframework.beans.factory.annotation.Autowired;
#Service
public class ServiceA {
private boolean test;
public ServiceA (){
test = true;
}
public changeValues(){
test = false;
}
}
#Service
public class ServiceB {
#Autowired
private ServiceA serivceA;
public void method1() {
serviceA.changeValues();
}
}
#Service
public class ServiceC {
#Autowired
private ServiceA serivceA;
public void method2(){
if(serviceA.getTest()){
doSomethingNeeded();
}
}
}
public class Application{
#Autowired
private ServiceB b;
#Autowired
private ServiceC c;
public static void main(String[] args) {
b.method1();
c.method2();
}
}
In this case the method doSomethingNeeded() in ServiceC won't be able to be executed because the ressource 'test' of ServiceA is shared between both ServiceB and ServiceC. How do I prevent That?
P.S. In my case, the dependency injections are way too complex for applying any modifications to the services, that's why I need a way to configure spring-ioc dependency injection in a way to create instances of private attributes to each client session.
Spring Beans are by default Singletons and the should not contain state.
Single Page Applications (like you create with Angular) should anyway hold the state on the client side and pass the information with every request.
The main reason is when your backend is stateless it's easy to scale and is more reliable because if a backend service is restarted you don't loose anything.
You just need change the scope of ServiceA to prototype by adding #Scope(scopeName = "prototype"):
#Scope(scopeName = "prototype")
#Service
public class ServiceA {
}
Then when ServiceB and ServiceC are instantiated , separated ServiceA will be created and inject into them.
P.S. Please note that a new instance of prototype bean will only be created during ServiceB and ServiceC are instantiated. It does not mean that a new instance of prototype bean will always be created whenever you access them. You need to use one of these technique if you want such behaviour.

Are autowired objects in spring-mvc threadsafe?

Question 1) From my understanding spring creates singletons objects, So when I have a controller like below with a autowired service, will that affect threadsafety.
Question 2) If I declare a int type variable at class level and use it in controller or service, will it affect thread safety?
#Controller
public class LoginController {
#Autowired
public DaoService daoservice;
#RequestMapping("/")
public String getBookInfo() {
Book book = daoservice.getBookbyId(1L);
System.out.println(book.getTitle());
return "welcome";
}
}
#Service
public class DaoService {
#Autowired
public BookRepository BookRepo;
public Book getBookbyId(Long Id) {
Book book = BookRepo.findOne(Id);
return book;
}
}
Q.1 : Are Spring Beans Thread Safe?
Answer: No.
Spring don't give you thread safety for their bean. Spring provide different type of bean scope like (Prototype,Singleton etc). If Prototype then a new bean create each time it invoke where a singleton bean created for one time and shared in application context.
If you are thinking for HTTP request, then 2 or more request can come.Hence new instance of a bean is created in each request scope. So you can think they are thread safe in context of HTTP request but it's not truly thread safe by spring itself.Because several thread can share the bean within the same HTTP request context.
Q.2 : Are Class variable Thread Safe?
Answer: No
Quoted from here
All private member variables are shared. They might be final, but that only means that the references can't be changed. Any mutable state must be synchronized.

Which #Scope should I choose for a stateful(?) #Service

I'm new to Spring.
I'm working on a library project which depends on spring-context.
#Scope(value = "##?")
#Service
public class MyService {
#PostConstruct private void constructed() {
}
#PreDestroying private void destroying() {
resource.clear();
}
public void doSome() throws IOException {
// try{}finally{} is not the case
resource = getSome();
doSome(resource); // may throw an IOException
resource.clear();
}
private transient MyResource resource;
}
I want to free the resource in every time this instance being destroyed.
According to #Scope, there four options that I can choose.
ConfigurableBeanFactory.SCOPE_SINGLETON
ConfigurableBeanFactory.SCOPE_PROTOTYPE
WebApplicationContext.SCOPE_REQUEST
WebApplicationContext.SCOPE_SESSION
I found that WebApplicationContext is not available from my dependency tree. (I'm not depends on spring-webmvc)
I'm planning to choose ConfigurableBeanFactory.SCOPE_PROTOTYPE.
Is it true that the scope I choose will make MyService safe? I mean any two or more clients can't be injected with the same service instance? Will the Spring container take care of it?
Indeed, Request, Session, Global-session and Application scopes are only available within Web aware application context.
Singleton (single instance per Spring container) is a default scope used by Spring, so using prototype scope will guarantee that new instance will be created and returned to the client, so yes Prototype is what you need in this case.

Create a stateful session bean from a stateless bean

The context is the following :
An client application uses a stateless session bean in order to login on an EJB server application. If the login is successful, the client should get a stateful session bean in order to perform some transactions on his personal data. However, I would want that the login method returns a new instance of this stateful session bean such that a client should not be able to manually call this session bean and perform transactions without being authenticated. Is it possible ?
In my stateless bean I have the following code :
#Resource
private SessionContext context;
...
public StatefulBeanRemote login(username, password) {
if (ok) {
StatefulBeanRemote bean = (StatefulBeanRemote) context.lookup("StatefulBeanRemote");
return bean;
}
The lookup always fail. I don't know what I am doing wrong...
The lookup you're performing is the same as:
new InitialContext().lookup("java:comp/env/StatefulBeanRemote");
Have you defined an EJB reference to StatefulBeanRemote? Perhaps that is all you need:
#EJB(name="StatefulBeanRemote", beanInterface=StatefulBeanRemote.class)
public class MyClass {
#Resource
private SessionContext context;
...
}

Problems injecting a BayeuxService into another class with annotations

I have a web app that is using Bayeux to handle Comet connections. I initialize a BayeuxServer and tie it into Spring annotations and it all works fine, listening on selected channels and responding.
I have a Jersey annotated class and an annotated Bayeux service as shown below. The idea is I wanted to be able to control resources via Rest from an individual web app, and then right after the resource is changed, do a server push via Comet to all other applicable clients to tell them to update their information.
Here is the problem: A Bayeux Service is created when the webapp is deployed, setting up proper channels to listen on and monitoring clients. There should only be one instance of this. When Jersey attempts to use the Bayeux service it creates a whole new service, when it should be using the original one. This new service doesn't have the BayeuxServer properly injected so I can't access client information through it.
It makes since that this should be doable, but I don't seem to understand how to inject these things properly via annotations. Can anyone point me in the right direction?
Jersey Annotated Class:
#Path("JsonTest")
public class JsonTest {
#Context
Request request;
#Context
UriInfo uriInfo;
#Context
ResourceContext resourceContext;
protected final Logger log = Logger.getLogger(getClass());
public JsonTest() {
}
#DELETE
#Path("{id}")
public void deleteJson(#PathParam("id") String id) {
JsonTestDao.instance.getModel().remove(id);
log.info("Deleted Json..." + id);
log.info("New json: " + JsonTestDao.instance.getModel().toString());
JsonTestService jsonTestService = resourceContext.getResource(JsonTestService.class);
jsonTestService.sendUpdate();
}
}
BayeuxService:
#Named
// Singleton here didn't seem to make a difference
#Service
public class JsonTestService {
protected final Logger log = Logger.getLogger(getClass());
#Inject
private BayeuxServer bayeux;
#Session
private ServerSession serverSession;
#PostConstruct
public void init() {
log.info("Initializing JsonTest Bayeux HelloService...");
log.info("Current sessions are: " + bayeux.getSessions().toString());
}
#Listener("/cometd/JsonTest")
public void jsonTestHandler(ServerSession remote, ServerMessage.Mutable message) {
}
public void sendUpdate() {
//bayeux.newMessage(); // Need a method that the Jersey class can call to notify changes
log.info("Bayeux server should be sending an update now...");
}
#PreDestroy
public void destroy() {
log.info("Destroying JsonTest Bayeux HelloService...");
}
}
See Jersey and spring integration - bean Injections are null at runtime.
Another question I asked. Both of these stem from the same problem involving properly setting the Jersey dependency and integrating it with spring.

Resources