Threads in Spring - java

I have a Web application using spring and hibernate and struts (it runs on Tomcat)
The call sequence is something like this...
Struts action calls spring service bean which in turn calls Spring DAO bean. The DAO implementation is a Hibernate implementation.
The question is
Would all my spring beans be running in the same thread ?
Can I store something in the ThreadLocal and get it in another bean?
I am quite sure this would not work in Stateless Session Bean.
The EJB container can (or will) spawn a new thread for every call to the session bean
Will the spring container do the same? i.e. run all beans in the same thread ?
When I tried a JUnit test - I got the same id via Thread.currentThread().getId() in the Test Case and the two beans- which leads me to believe there was only one thread in action
Or is the behavior unpredictable?
Or will it change when running on Tomcat server ?
Clarification
I do not wish to exchange data between two threads. I want to put data in the ThreadLocal and be able to retrieve it from all beans in the call stack. This will work only if all beans are in the same thread

Spring doesn't spawn the threads. Tomcat does. Spring is just creating and wiring up the objects for you.
Each request from the browser is processed in one request. It is Tomcat that handles the request. It is Tomcat that creates the thread to process the request.
Assuming you have just created a singleton bean in Spring called "X". Then the same instance of X is used by all requests.
The Spring beans don't live in a thread. They are just allocated on the heap.

Would all my spring beans be running
in the same thread ? Can I store
something in the ThreadLocal and get
it in another bean?
AFAIK for the components you mentioned (service bean, DAO bean - i guess they are plain spring beans), Spring does not spawn a new thread. I do not understand your use case (ie, exchanging data between two threads).
For most webapps, a new thread is spawned for each new request, and if you want to share data between two requests you normally:
- use the get/post parameters to pass the data
- use the session to share data
To answer your question, I'm pretty sure the spring container does not spawn threads for most components.

Yes, you can do this. The same thread will be used to execute your action so the ThreadLocal will work. Typically, the same thread is used for the stateless session bean as well, assuming it is running in the same app server instance. I would not depend on this though, as it is probably vendor dependent.
We use this technique to access the callers identity anywhere in the code. We use session beans and jms as well, but explicitly pass the information between containers and set the ThreadLocal at each entry point. This way it doesn't matter if the bean (session or mdb) are local or not.

In addition to all the other answers, I will just add the following:
Normally the only reason to switch threads is because of some requirement for parallellity. Since this normally does not come for free in terms of complexity, you will usually be clearly informed when this happens.
Switching threads within what appears to be a single-threaded processing of a request is actually extremely complex. This will normally only happen at one place in a container, and this is usually handled by tcp/ip socket readers that receive the request from the external clients. These reader threads usually determine which thread(pool) should process the request and forward the request to that thread. After that the request stays with that thread.
So normally the only thing that will/can happen is that additional threads get created for parallelity or asynchronous processing (like JMS).

Related

Execute method after Spring context initialized but before requests are accepted

In a spring boot app (2.3), is it possible to have a method be executed after context is initialized, but before the app starts to take requests? I don't know if becoming ready to accept requests is part of the spring context initialization or if that is a separate step.
Note that ideally if this method throws an exception, the service fails to start, but that is not a requirement.
I tried ContextRefreshedEvent. However, the app is accepting requests at that point. (While my ContextRefreshedEvent event listener method is executing, requests can come in and execute at the same time.)
(I can't use #PostContruct, because my method depends on many different beans being initialized.)
The specific use case is that I have a spring cloud config server. I want it to pre-load authentication data into cache prior to accepting requests. The loading of this data depends on bootstrap/app config files being loaded, ApplicationEnvironmentPreparedEvent listener being called, beans being constructed, etc.
As Andy Wilkinson pointed out (thank you!), to do this, implement a bean's method with the desired behavior and add the #PostConstruct annotation. The method will be called after all beans are initialized (and environment prepared) but before the service starts taking requests.

Overview of Tomcat/Java vs PHP

Couldn't find this info in google or by asking people in discord programming servers.
Before I ask the main question I wanna confirm something first:
When java runs in tomcat, lets say like in case of Spring Boot application with Tomcat built in it:
all the components managed by ioc container: #controller/#configuration/#service, and other annotations that indicate that class should be managed by the container, do all these components get instantiated in container on startup of the application, before any http request comes from the client ? All the different controllers for many different, routes, do they get instantiated before they are actually needed to process any request ?
if so, do all these instances of these components get used to process all subsequent incoming requests ? like a controller instance wouldnt be destroyed by GC after a request was processed and response was returned to client ? this controller is always kept in memory(heap I guess) until application stops running ?
when a new http request comes to tomcat from client, does some new thread get created to process this request ? does this thread use the same instance of controller and other components managed by container to process the request ?
Now main question.
In PHP the whole new process is started when server starts index.php file and passes the request to it to process it. And php programs also have ioc containers, PDOs, repositories, etc - the components that are manage by container. Container can be self made by developers or provided by FW like symfony, laminas, laravel.
Does this mean that whenever a request is processed by PHP program, all the possible controllers get instantiated in IOC container, get their dependencies injected, but since requests usually need just 1 controller to be processed, all the other controllers and components that got created on startup of app and IOC container, they got just created for nothing, got never used, and then app just died without doing anything with those unused controllers/components, except the 1 controller that was matched by the route of the request ?
To answer your PHP question:
If a container is done right, it should instantiate ONLY the classes you use during the current request. If you use a single controller - it should make a single instance of that controller and inject all dependencies into it.
If a container makes instances of all possible classes that can be loaded through it - it will be extremely inefficient.
Usually the Containers keeps track of HOW to instantiate every possible instance that you might need. Like a config file. Graph of dependencies of every class that can be loaded from the container. etc.
That means the container KNOWS how to instantiate every class configurable through it, but it instantiates only the ones you use in the current request.
Also it should load only the files needed by the current request. Not all of them. However, if you use OPCache extension, they will not be parsed every time, but will be kept in a compiled variant in-memory of the PHP-FPM process.

Update injected domain object in Java EE 7 CDI Application

This may be more of a conceptual than technical question however I hope you can provide me some advice on how to proceed.
We are developing a large Java EE 7 application that works stateless and is getting requests from clients. Each request contains a session ID and each session contains a large amount of domain objects that are session specific.
We created a RequestScoped class that contains all the producer methods for our domain objects. When a request comes in with a session ID we call a setter Method on the producer to set the session ID in the producer CDI bean.
Now if one of the RequestScoped classes along the chain needs one of the domain objects it has an #Inject definition at the beginning of the class to get the domain object from the producer. The Producer itself has a connection to an inmemory DB to retrieve the domain objects from there and keep them in a local variable for future use in this request.
Now to the question: Say Bean A injects Domain Object X and changes some properties on X. Do I have to call an "update" Method in my producer and pass Domain Object X as a parameter or is it updated automatically in the context?
Upon injection in the Request Scope the CDI container creates a proxy to access the actual bean. Would this proxy be usable just like a regular reference? E.g. if I call a method on my injected bean, would it update the bean behind the proxy?
I know this will probably get me downvoted, but I'll answer anyway because I'm hoping it'll be valuable to you. It sounds like you guys have put the cart a mile in front of the horse.
The Producer itself has a connection to an inmemory DB to retrieve the domain objects from there and keep them in a local variable for future use in this request.
You're trying to re-invent what's called replicated, distributed, sessions. Don't do this. Use #SessionScoped beans and keep the business logic in your app, and let your infrastructure handle the application state. Imagine yourself years from now looking at this application, when your boss wants a UI refresh and your customers are demanding new features. You're going to not only maintain the application, but an entire mess of a buggy distributed framework you built :(
Instead, you can use a distributed in-memory DB to hold your session state and cache it locally! Apache Tomcat/TomEE has great support for this (I'm not sure what application server you are using)
Take a look at:
https://github.com/magro/memcached-session-manager (Use Couchbase, Redis, Memcached, Hazelcast, GridGrain, or Apache Geode)
http://community.gemstone.com/display/gemfire/Setting+Up+GemFire+HTTP+Session+Management+for+Tomcat (Specific to Gemfire)
We use the first with great success. If the Tomcat instance encounters a session id it doesn't have locally, it pulls it from the data grid. When it's done processing the request, it publishes that session changes back to the data grid. This is extremely fast and scales beautifully.
If your application server does not have the ability to do this, instead of writing the application in the painful manner you are doing, I would concentrate your efforts on writing a session replicator like memcached-session-manager. Good luck!

How do I timeout a blocking call inside an EJB?

I am in the process of developing an EJB that makes 10+ calls to other components (EJBs, Web services, etc.) as part of it's business logic. In my case, performance is a huge concern. This EJB will be servicing a few million requests a day.
My question is: For each of those 10+ calls, how can I enforce a timeout?
I cannot wait more than 'n' seconds for any one of the calls to return. If a call takes longer than 'n' seconds, I will use a default response for processing.
I would normally use a Executor to solve this problem but, from what I understand, one shouldn't spawn threads from within an EJB as it may potentially interfere with the EJB's lifecycle.
how can I enforce a timeout?
The ejb3.1 specification provides the possibility to set a timeout using #AccessTimeout annotation that applies for serialized client calls that have to wait when an Session Bean instance
is busy executing a previous request.
Clearly (and explicity described in the specification) this applies to StateFul and Singleton session bean, although it could be implemented for Stateless in the case the bean pool run out of available instances.
Notice, once the client-invoked business method is in progress this timeout no applies.
Other possibility that is not part of the specification but, is supported by several servers (see JBoss example) is to define a timeout at the remote client side. If the client invocation
takes longer than the configured timeout, the client will be informed, however, the server execution will not be interrupted which it is not good enough.
Set a transaction timeout neither is a good option because there is no guarantee the thread that executes the business logic will be interrupted when the transaction timeout expires.
I would normally use a Executor to solve this problem but, from what I understand, one shouldn't spawn threads from within an EJB..
Instead you could use ManagedExecutorService class that is an Executor extension suitable to use within a EJB Container.
Aditionally, to implement asynchronous call within an EJB, take a look at #Asynchronous annotation, which provides a high level abstraction to solve the multithreding issue you are facing.
Cancel() method from Future class, allows you to interrup a thread's execution if you consider that the process has taken too long.
since you are not providing much detail of your environment:
use bean managed transactions and set the transaction timeout
EE7: provides an managed executor service
EE6: custom executor service as a JCA connector

How to share data/objects between client service calls on the serverside with Spring?

I'm currently using Spring and Hibernate. At the moment, if I make a create object call (for example) from the client a request comes in on the service stub on the serverside. The service call has to create a new hibernate session factory, get the session, and then make the transaction. The problem is that this occurs every single time, so the session factory needs to be recreated to be used. This seems to be extremely wasteful and performance impacting since creating that factory takes a toll.
What I would like to do is reuse that one session factory, for example, across different service calls made by the client or multiple clients. The problem is I don't know how to do that since the entry point to the serverside functionality is the service call. I know that I would have to save state on the serverside somehow so that different calls could access the same session factory. I know of the scalability issues with keeping state and such, but there has to be a way to reuse previously created objects.
My question is how would I do this with Spring (am I supposed to use Session beans or HttpSession)? Is it possible for the container to set these things up on startup or does it have to wait for a service request to come in?
I'm for the most part a Spring newb, is it just that I don't understand the web service role?
Thanks in advance.
Yours is typical MVC scenario which is achieved by GWT+MVP. Based on your description seems you are creating the session-factory on every call which is obviously not a standard practice.
Session-factory is created only once and every request executes in a different session created by the session-factory.
With Spring, typical approach would be to configure the session-factory with spring wiring and hibernate. This config will be loaded only once when application starts up.
On every service request, get the reference of session-factory from the bean-container (instead of creating it every time) and create session from it for DB operation.
Check out this project which uses GWT+MVP+Spring+MyBatis. I understand that you use Hibernate instead of MyBatis but this would server as reference for this type of project.

Categories

Resources