Work around Hibernate's errors in multithreaded applications - java

Because of all the problems we can meet when trying to use Hibernate in a multithreaded application (1st clue, 2nd clue, 3rd clue, etc.), I was thinking of another solution: implementing the logical part within a classic Controller, and simply call it from my thread using URL.openConnection().
In other words, instead of doing something like this:
MyThread.java
public class MyThread implements Runnable {
#Override
public void run() {
// do some great stuff with Hibernate
}
}
Anywhere.java
new Thread(new MyThread()).start();
I would like to try something like that:
MyController.java
#Controller
public class MyController {
#RequestMapping(value = "myUrl", method = RequestMethod.GET)
public void myMethod() {
// do some great stuff with Hibernate
}
}
MyThread.java
public class MyThread implements Runnable {
#Override
public void run() {
// simple call the above mapped url
}
}
Anywhere.java
new Thread(new MyThread()).start();
What do you think about it? Good or bad? I haven't tried yet, but I think such a solution will prevent the common errors we can meet using Hibernate in multithreading, because the server will execute the logical part as if someone were requesting the fake page.
PS: I know there are some solutions to use Hibernate in multithreaded applications, but each time I try one, another appears, and that until the I'm-fed-up-with-it point of no return.
PS2: I'm aware that such a solution need to be secured (e.g. UID as a token).

I don't really see what problem you're trying to solve here. Hibernate is almost always used in a multi-threaded environment. In webapps, for example, concurrent requests are handled by multiple concurrent threads, and each thread uses its own Hibernate session. And that doesn't cause any problem.
You will have problem if you share the same session among threads, or if you share a given entity among threads.
If you start your own thread, and this thread uses its own session and entities, I don't see why you would have any problem.

Related

Access local resources with hazelcast scheduled job

I'm very new to Hazelcast, and it might very well be that I am missing something glaringly obvious, but here goes.
I have a Java Application that runs distributed, each containing its own Hazelcast Instance. I need Hazelcast to schedule a job that will run at a fixed rate, but never simultaneously on several instances. To achieve this I plan to use the IScheduledExecutorService and create a job that implements Runnable and NamedTask.
My problem is that the job needs to call methods on the application. My understanding is that the job is serialized and deserialized by hazelcast, which means that I can't just create a Runnable and feed it the objects it needs through its constructor. So how do I "Get back" to the application objects from the Hazelcast job?
For example, say I had a plain old java Runnable that i would like to execute in a Hazelcast Executor like this:
public class DoStuffJob implements Runnable, NamedTask {
private MyResource resource;
public DoStuffJob (MyResource resource){
this.resource = resource;
}
#Override
public String getName() {
return "Do stuff";
}
#Override
public void run() {
resource.doAllTheStuff();
}
}
How would I create a Runnable I can execute on Hazelcast, that can still access MyResource on the instance it executes on?
The only option I have found is to make the job HazelcastInstanceAware, and use the HazelcastInstance.getUserContext() to keep the object, but I am hoping it is somehow possible to "get back" to the executing application.
Thank you in advance.
You could have your Runnable task put the derived data into a distributed data-structure - probably an IMap. It would then be accessible from any of your JVMs. Would that handle your requirements?

Hibernate/JPA TransactionManagment

First of All I have to apologize for the semi-psuedo code as the classes I am going to reference are all too big and are pointless except for a few lines of each class to ask my question.
To Start off I am using
Jboss 6.3.2 EAP
Hibernate
EJB 3.0
I have two different EJB Classes
They are
Service Layer
#Stateless
#TransactionManagement
#TransactionAttribute(TransactionAttributeType.NOT_SUPPORTED)
public class ServiceClass implements ILocalService
{
#EJB
ILocalDao localDao;
#Override
public myObject find(String id)
{
localDao.findByPK(id);
}
#TransactionalAttribute(TransactionAttributeType.REQUIRED)
#Override
public void create(myObject obj)
{
localDao.create(obj);
}
#TransactionalAttribute(TransactionAttributeType.REQUIRED)
#Override
public void update(myObject obj)
{
localDao.findByPK(obj.getId());
localDao.update(obj);
}
}
DAO Layer
#Stateless
#TransactionalAttribute(TransactionAttributeType.MANDATORY)
public class DaoClass extends AbstractDaoClass<myObject> implements ILocalDao
{
#Override
public myObject findByPK(String id)
{
super.find(id);
}
}
Okay with those two classes laid out. Trust me that everything else is correctly configured interface Classes, Abstract Class, persistence.xml, etc.
The question is How does the find method in the ServiceClass work? With the NOT_SUPPORTED being assigned to this method I would think that the DaoClass call would throw a Exception because no Transaction has been started yet and I am making the entire class MANDATORY. But my running app says otherwise.
To verify that no transaction is being created on the DaoClass.find method. I put in the #TransactionalAttribute(TransactionAttributeType.NEVER). And re-ran the application. Still works.
To verify that the NEVER works I call the ServiceClass's update method. Throws an exception as expected.
To round this all out I have looked at many online resources(http://docs.oracle.com/javaee/6/tutorial/doc/bncij.html, etc) I have looked into the source files for the EJB 3.0 and Jboss...I am not seeing anything.
So questions I have pondered
Is the TransctionAttributeType.MANDATORY on the class level not
working as I expect it to in the DaoClass?
TransactionManagement on the ServiceClass creating a Transaction on init of the ServiceClass and then the NOT_SUPPORTED suspending this transaction?
I am in the process of writing up some tests to hopefully log the transaction's behavior and see what is going on. But hopefully someone here can shed some light sooner and relieve this huge question mark I have.
Thanks in advance.
First, #TransactionManagement without parameters is useless, since default value is TransactionManagementType.CONTAINER and EJB uses TransactionManagementType.CONTAINER implicitly.

Multi Threaded Application with (Spring) ThreadPoolTaskExecutor

I need to implement Multi Threaded background process. My project is spring , hibernate based I tried with below code which uses org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor to perform the
below background operation in multi threaded manner.
I need to know
If I use Spring ThreadPoolTaskExecutor is this multi threaded?
Will there be overlapping issues like multiple threads acqure the same user object ?
If "YES" Should I need to use synchronize the method upgradeUserInBackground() to avoid
such a situations ? Alternative solution ?
public class UserUpdateProcessor implements InitializingBean {
private ThreadPoolTaskExecutor executor;
public void afterPropertiesSet() throws Exception {
executor.execute(new UserBackgorundRunner ());
}
}
private class UserBackgorundRunner extends Thread {
public UserBackgorundRunner() {
this.setDaemon(true);
this.setPriority(MIN_PRIORITY);
}
public void run() {
List<User> users = getUserList();;
for (User user : users) {
try {
upgradeUserInBackground(user);
} catch (Exception e) {
LOGGER.warn("Fail to upgrade user");
}
}
}
Yes, it is multi threaded, all submitted tasks will be executed at the same time. Spring takes care of thread starvation as well so there will be parallel execution always until you try some hacks.
Yes, there may be overlapping issues like multiple threads acqure the same user object.
For your scenario i would advice you to use Spring Batch FMK and configure/hack it for not saving any data in database. It will give you concurrency, speed, reliability and solution of overlapping objects using tasklet "scope".
If you use synchronization in threads, it is considered to be a bad design, rethink your problem.

How to avoid concurrent access of controller method with the same session in java spring?

I would like to know how to make sure that some method in a service is accessed only once at a time per session.
I'll illustrate by a small example:
Assume we have a user in a state A (user.state = A). This user sends a HTTP GET request to our java spring controller to get a page, say /hello. Based on his status, he will be sent to either A or B. Before that, we will change his status to B (see code below).
Now, assume again that the call dao.doSomething(); takes a lot of time. If the user sends another GET (by refreshing his browser for instance), he will call the exact same method dao.doSomething(), resulting in 2 calls.
How can you avoid that?
What happens if you sends 2 HTTP GETs at the same time?
How can you have something consistent in your controller/service/model/database?
Note 1: here we don't issue the 2 HTTP GETs from different browser. We just make them at the same time on the same browser (I'm aware of the max concurrent session solution, but this does not solve my problem.).
Note 2: the solution should not block concurrent accesses of the controller for different users.
I've read a bit about transaction on service, but I'm not sure if this is the solution. I've also read a bit on concurrency, but I still don't understand how to use it here.
I would greatly appreciate your help! Thanks!
code example:
#Controller
public class UserController {
#RequestMapping(value='/hello')
public String viewHelloPage() {
// we get the user from a session attribute
if (user.getState() = A) {
user.setStatus(B);
return "pageA";
}
return "pageB";
}
#Service
public class UserService {
Dao dao;
#Override
public void setStatus(User user) {
dao.doSomething();
user.setStatus(B);
}
}
Although I wouldn't recommend it (as it basically blocks all other calls from the same user to). On most HandlerAdapter implementations you can set the property synchronizeOnSession by default this is false allowing for concurrent requests to come from the same client. When you set this property to true requests will be queued for that client.
How to set it depends on your configuration of the HandlerAdapter.
how to make sure that some method in a service is accessed only once
at a time per session.
Try to Lock on session object in your controller before calling service method
If dao.doSomething() is doing work that you only want to happen once, you should use an idempotent method like PUT or DELETE. There's no law forcing you to use the correct method, but worst-case it's a self-documenting way to tell the world about how your API should be used. If that isn't enough for you, most browsers will try to help you out based on the type of request. For instance, the browser will often use caching to avoid multiple GETs.
It seems like what you really want to know is how to enforce idempotency. This is very application-specific. One general approach is to generate and store a pseudo-unique id on the server side for the client to attach to their request. This way, any request with the same id after the first can be safely ignored. Obviously old ids should be evicted intelligently.
As I said, the solution is often application-specific. In your case above, it looks like you're trying to switch between 2 states, and your implementation is a server-side toggle. You can utilize the client to ensure that multiple requests will not be a problem.
#RequestMapping(value="/hello", method=RequestMethod.PUT)
public String test(#RequestParam("state") String state) {
dao.setState(user, state)
switch (state) {
case "A":
return "B";
case "B":
return "A";
default:
return "error";
}
}
If you don't mind to configure and use AOP, then the following might help you
#Aspect
#Component
public class NonConcurrentAspect implements HttpSessionListener{
private Map<HttpSession, Map<Method, Object>> mutexes = new ConcurrentHashMap<HttpSession, Map<Method, Object>>();
#Around(value = "#annotation(org.springframework.web.bind.annotation.RequestMapping)")
public Object handle(ProceedingJoinPoint pjp) throws Throwable {
MethodInvocationProceedingJoinPoint methodPjp = (MethodInvocationProceedingJoinPoint) pjp;
Method method = ((MethodSignature) methodPjp.getSignature()).getMethod();
ServletRequestAttributes requestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
HttpServletRequest request = requestAttributes.getRequest();
HttpSession session = request.getSession(false);
Object mutex = getMutex(session, method);
synchronized (mutex) {
return pjp.proceed();
}
}
private Object getMutex(HttpSession session, Method method) {
Map<Method, Object> sessionMutexes = mutexes.get(session);
Object mutex = new Object();
Object existingMutex = sessionMutexes.putIfAbsent(method, mutex);
return existingMutex == null ? mutex : existingMutex;
}
#Override
public void sessionCreated(HttpSessionEvent se) {
mutexes.put(se.getSession(), new ConcurrentHashMap<Method, Object>());
}
#Override
public void sessionDestroyed(HttpSessionEvent se) {
mutexes.remove(se.getSession());
}
}
It synchronizes on a per-session per-method mutex. One restriction is that the methods so advised should not call each other (which is hardly a case, unless you violate MVC design pattern severely), otherwise you may face deadlocks.
This would handle all the methods tagged with #RequestMapping, but if you want just few methods be guarded against concurrent execution,
then, as one of the possible solutions, you could introduce your own annotation, e.g.
#Target(ElementType.METHOD)
#Retention(RetentionPolicy.RUNTIME)
#Documented
public #interface NonConcurrent {
}
tag the specific methods with this annotation, and replace #RequestMapping in #Around annotation in the above aspect class with your own.
In highly contended environment you may think of more advanced solution than intrinsic locks.
I would, however, advise against using HandlerAdapter's synchronizeOnSession option, not only because it synchronizes all the invocations on the same mutex, but, which is less obvious, the synchronization on publicly available mutex is potentially dangerous.

Run Spring class asynchronously

I'm working in an Spring application that downloads data from different APIs. For that purpose I need a class Fetcher that interacts with an API to fetch the needed data. One of the requirements of this class is that it has to have a method to start the fetching and a method to stop it. Also, it must download all asynchronously because users must be able to interact with a dashboard while fetching data.
Which is the best way to accomplish this? I've been reading about task executors and the different annotations of Spring to schedule tasks and execute them asynchronously but this solutions don't seem to solve my problem.
Asynchronous task execution is what you're after and since Spring 3.0 you can achieve this using annotations too directly on the method you want to run asyncrhonously.
There are two ways of implementing this depending whether you are interested in getting a result from the async process:
#Async
public Future<ReturnPOJO> asyncTaskWithReturn(){
//..
return new AsyncResult<ReturnPOJO>(yourReturnPOJOInstance);
}
or not:
#Async
public void asyncTaskNoReturn() {
//..
}
In the former method the result of your computation conveyed by yourReturnPOJOInstance object instance, is stored in an instance of org.springframework.scheduling.annotation.AsyncResult<V> which in return implements the java.util.concurrent.Future<V> that the caller can use to retrieve the result of the computation later on.
To activate the above functionality in Spring you have to add in your XML config file:
<task: annotation-driven />
along with the needed task namespace.
The simplest way to do this is to use the Thread class. You supply a Runnable object that performs the fetching functionality in the run() method and when the Thread is started, it invokes the run method in a separate thread of execution.
So something like this:
public class Fetcher implements Runnable{
public void run(){
//do fetching stuff
}
}
//in your code
Thread fetchThread = new Thread(new Fetcher());
fetchThread.start();
Now, if you want to be able to cancel, you can do that a couple of ways. The easiest (albeit most violent and nonadvisable way to do it is to interrupt the thread:
fetchThread.interrupt();
The correct way to do it would be to implement logic in your Fetcher class that periodically checks a variable to see whether it should stop doing whatever it's doing or not.
Edit To your question about getting Spring to run it automatically, if you wanted it to run periodically, you'll need to use a scheduling framework like Quartz. However, if you just want it to run once what you could do is use the #PostConstruct annotation. The method annotated with #PostConstruct will be executed after the bean is created. So you could do something like this
#Service
public class Fetcher implements Runnable{
public void run(){
//do stuff
}
#PostConstruct
public void goDoIt(){
Thread trd = new Thread(this);
trd.start();
}
}
Edit 2 I actually didn't know about this, but check out the #Async discussion in the Spring documentation if you haven't already. Might also be what you want to do.
You might only need certain methods to run on a separate thread rather than the entire class. If so, the #Async annotation is so simple and easy to use.
Simply add it to any method you want to run asynchronously, you can also use it on methods with return types thanks to Java's Future library.
Check out this page: http://www.baeldung.com/spring-async

Categories

Resources