I need to create a process that will query a webservice to extract information, and then save the data in my database. However, because this process is very time-intensive, I would like to make it run in the background.
Currently, I have a ProcessHandler which is invoked by a button in the UI. This handler creates a Thread which should run the process in the background. However, I am getting HibernateException with the message No Hibernate Session bound to thread, and configuration does not allow creation of non-transactional one here.
I have defined ProcessHandler in one of the config xml files (there are several) as follows (this is a very generic definition):
<bean class="com.project.ProcessHandler" parent="parentHandler" />
Inside ProcessHandler, the code to invoke this process is also very generic:
Thread t = new Thread(new WorkerThread(alphaManager, bravoManager, charlieManager));
t.start();
This is the current implementation of WorkerThread:
public class WorkerThread implements Runnable {
private Manager alphaManager;
private Manager bravoManager;
private Manager charlieManager;
public WorkerThread() {
this.alphaManager = null;
this.bravoManager = null;
this.charlieManager= null;
}
public WorkerThread(Manager alphaManager, Manager bravoManager, Manager charlieManager) {
this.alphaManager = alphaManager;
this.bravoManager = bravoManager;
this.charlieManager= charlieManager;
}
#Override
public void run() {
// code to query webservice and extract data...
saveToDbMethod(data);
}
#Transactional(propagation = Propagation.REQUIRED)
private void saveToDbMethod(String data) {
// code to process data...
alphaManager.save(entityA);
bravoManager.save(entityB);
charlieManager.save(entityC);
}
}
The default constructor is a leftover from when I tried to define WorkerThread as a bean in (one of) my config xml files.
Can anyone help me by giving me some tips on how to troubleshoot this?
The problem is that you create the Thread manually and expecting it behave like a spring managed bean.
As the ProcessHandler is a legitimate bean, what i would do is following:
1) Create a seaparate service class which would have the managers as dependencies and that #Transactional method:
#Service
public class Service{
private Manager alphaManager;
private Manager bravoManager;
private Manager charlieManager;
public Service(Manager alphaManager, Manager bravoManager, Manager charlieManager) {
this.alphaManager = alphaManager;
this.bravoManager = bravoManager;
this.charlieManager= charlieManager;
}
#Transactional(propagation = Propagation.REQUIRED)
private void saveToDbMethod(String data) {
// code to process data...
alphaManager.save(entityA);
bravoManager.save(entityB);
charlieManager.save(entityC);
}
}
2) Inject the Service into the ProcessHandler:
<bean class="com.project.ProcessHandler" parent="parentHandler">
<property name="service" ref="service">
</bean>
3) Finally pass the Service to the WorkerThread:
public class WorkerThread implements Runnable {
private Service service;
public WorkerThread(Service service) {
this.service = service;
}
#Override
public void run() {
// code to query webservice and extract data...
service.saveToDbMethod(data);
}
}
and:
Thread t = new Thread(new WorkerThread(service));
t.start();
Now your operations should be transactional and within a session.
Related
I am having troubles invoking a method asynchronously in Spring, when the invoker is an embedded library receiving notifications from an external system. The code looks as below:
#Service
public class DefaultNotificationProcessor implements NotificationProcessor {
private NotificationClient client;
#Override
public void process(Notification notification) {
processAsync(notification);
}
#PostConstruct
public void startClient() {
client = new NotificationClient(this, clientPort);
client.start();
}
#PreDestroy
public void stopClient() {
client.stop();
}
#Async
private void processAsync(Notification notification) {
// Heavy processing
}
}
The NotificationClient internally has a thread in which it receives notifications from another system. It accepts a NotificationProcessor in its constructor which is basically the object that will do the actual processing of notifications.
In the above code, I have given the Spring bean as the processor and attempted to process the notification asynchronously by using #Async annotation. However, it appears the notification is processed in the same thread as the one used by NotificationClient. Effectively, #Async is ignored.
What am I missing here?
#Async (as well as #Transactional and other similar annotations) will not work when the method is invoked via this (on when #Async is used for private methods*), as long as you do not use real AspectJ compiletime or runtime weaving.
*the private method thing is: when the method is private, then it must been invoked via this - so this is more the consequence then the cause
So change your code:
#Service
public class DefaultNotificationProcessor implements NotificationProcessor {
#Resource
private DefaultNotificationProcessor selfReference;
#Override
public void process(Notification notification) {
selfReference.processAsync(notification);
}
//the method must not been private
//the method must been invoked via a bean reference
#Async
void processAsync(Notification notification) {
// Heavy processing
}
}
See also the answers for: Does Spring #Transactional attribute work on a private method? -- this is the same problem
When the first runnable is submitted is an inject ExecutorService, the security Principal is correctly set for that runnable. Each subsequently submitted runnable is given the security principal of the original user instead of keeping the current runnable. My development machine is running Wildfly 8.2 .
I am creating a reporting system for asynchronous processing. I created a service that checks which user created the task and ensures that only that user can start or complete the task. The code for the service is below.
#Stateless
public class ReportingService {
//EE injection security context
#Resource
SessionContext context;
//CDI security Principal
#Inject
Principal principal;
//this method handles getting the username for EE injection or CDI
private String getCurrentUser() {
if (context != null) {
return context.getCallerPrincipal().getName();
}
if (principal != null) {
return principal.getName();
}
return null;
}
#TransactionAttribute(TransactionAttributeType.REQUIRES_NEW)
#Transactional
public void registerTask(String taskId) {
//Create task
//set task.submittedBy = getCurrentUser()
//persist task
//code has been omitted since it is working
}
private void validateCurrentUserRegisteredJob(String taskId) {
String user = //get user that created task with id = id from DB
String currentUser = getCurrentUser();
if (!user.equals(currentUser)) {
throw new EJBAccesException("Current user "+currentUser+" did not register task");
}
}
#TransactionAttribute(TransactionAttributeType.REQUIRES_NEW)
#Transactional
public void startTask(String taskId) {
validateCurrentUserRegisteredJob(taskid);
//retrieve task entity, set start time to now, and merge
}
...
}
Below is my Runnable code
public TaskRunner() implements Runnable {
//CDI principal
#Inject
Principal principal;
#Inject
ReportingService rs;
private taskId;
public void setTaskId() {...}
public void run() {
log.debug("Inside Runner Current User: "+principal.getName());
rs.startTask(taskId);
....
}
}
The following is the code from the Stateless Bean that is called by a REST endpoint that kicks off the process
#Stateless
public ProjectService() {
#Inject
Instance<TaskRunner> taskRunner;
#Inject
ReportingService reportingService;
//ExecutorService that is create from Adam Bien's porcupine project
#Inject
#Dedicated
ExecutorService es;
//method that is called by rest enpoint to kick off
public void performAsynchAction(List<String> taskIds, ...rest of args...) {
taskIds.stream().forEach(t -> {
//registers task with user that made REST call
reportingService.registerTask(t);
TaskRunner runner = taskRunner.get();
runner.setTaskId(t);
log.debug("Created runner. Principal: "+runner.principal.getName());
es.submit(runner);
});
}
}
Here is the chart of the call flow
REST -> ProjectService.performAsynchAction(...)
-> reportingService.registerTask(...)
-> create CDI injected Runnable
-> submit runner to executor service
-> ExecutorService calls Runner.run()
-> rs.startTask(taskId)
I call the Rest end point as user1 for the first time and register tasks: 1-2. They all work as expected and I get the following output in my log.
Created runner. Principal: user1
Created runner. Principal: user1
Inside Runner Current User: user1
Inside Runner Current User: user1
The next time I make the same REST call as user2 and I get the following output in the log
Created runner. Principal: user2
Inside Runner Current User: user1
EJBAccessException Current user user1 did not register task
It appears that the Security Principal of the Runnable is correctly set the first time a Runnable is submitted to the ExecutorService. But for each subsequent Runneable that is submitted to the ExecutorService uses the security Principal of the first submitted runnable. Is this a bug or the intended behavior? Does anyone know of a potential work around?
EDIT: I figure out that the porcupine project I was using to create the ExecutorService was not being managed by the container. Once I switched to a ManagedExecutorService, the SessionContext was being properly propagated.
#Resource(lookup = "java:jboss/ee/concurrency/executor/customExecutor")
private ManagedExecutorService es;
I figured out the issue. I looked into the porcupine code and found out that the ExecutorService was not being managed by the Container. I created a ManagerExecutorService and the SessionContext was then being properly propogated.
#Resource(lookup = "java:jboss/ee/concurrency/executor/customExecutor")
private ManagedExecutorService es_;
I think the problem is, that you #Inject a #Dependent scoped ExecutorService into a #Stateless bean.
#Stateless beans can be pooled and reused, while #Dependent CDI beans are stored by reference and therefore are not recreated when the #Stateless bean is reused.
Without knowing the implementation of your ExecutorService, I guess that it creates contextual threads during the first run and reused them in the second run without adjusting the context.
You could "force" your ProjectService to create a new ExecutorService by encapsulating it into a #RequestScoped bean:
#RequestScoped
public class ESHolder {
#Inject
#Dedicated
ExecutorService eS;
public ExecutorService getES() {
return eS;
}
}
#Stateless
public ProjectService() {
// ...
#Inject
ESHolder esHolder;
public void performAsynchAction(List<String> taskIds, ...rest of args...) {
taskIds.stream().forEach(t -> {
// ...
esHolder.getES().submit(runner);
});
}
}
I'm using play framework and JPA. Few messages are passed to the Akka Actors to async processing. Inside async process, I need to connect my database through JPA.
public class OrderCreation extends UntypedActor {
private EntityManagerFactory emFact = null;
private ActorSelection provisioner;
#Transactional(readOnly = false)
#Override
public void onReceive(Object order) throws Exception {
//HERE I need to do JPA related transactions
}
#Override
public void postStop() throws Exception {
}
#Override
public void preStart() throws Exception {
provisioner =getContext().actorSelection("/user/OrderProvisioner");
emFact = Persistence.createEntityManagerFactory("test-data-play");
}
}
I got this error
[akka://application/user/OrderCreation] No EntityManager bound to this thread. Try wrapping this call in JPA.withTransaction, or ensure that the HTTP context is setup on this thread.
java.lang.RuntimeException: No EntityManager bound to this thread. Try wrapping this call in JPA.withTransaction, or ensure that the HTTP context is setup on this thread.
at play.db.jpa.JPA.em(JPA.java:58)
Anybody has an idea to connect JPA through Akka?
#Transactional is an action composition, it will only work in Controllers.
You need to inject JPAApi in your actor and use jpaApi.withTransaction method to create/attach EntityManager to the thread and wrap you code within a transaction.
I would like to know what could be the best architecture for a RESTful web service with a single thread executor.
My goal :
Call a RESTful web service
The web service add a task in a thread queue and execute all the task 1 per 1.
The life cyle of instanciated object is really important (there must be only one thread queue). I know that a RESTful web service life cycle is "per request" (similar to #RequestScoped I think), so I see 2 options :
Option 1 :
public class RestService {
protected final static Executor executor;
protected final static Implementation1 impl1;
protected final static Implementation2 impl2;
static {
executor = Executors.newSingleThreadExecutor();
impl1 = new Implementation1();
impl2 = new Implementation2();
}
}
#Path("/servicename")
public class MyService extends RestService {
#POST
#Path("/compute")
public void compute(){
executor.execute(new Runnable(){
public void run(){
impl1.compute();
}
});
}
}
Option 2 :
#Singleton
public class RestService {
private Executor executor;
private Implementation1 impl1;
private Implementation2 impl2;
public RestService () {
executor = Executors.newSingleThreadExecutor();
impl1 = new Implementation1();
impl2 = new Implementation2();
}
public void execute(Runnable run){
executor.execute(run);
}
public Implementation1 getImplementation1(){
return impl1;
}
public Implementation2 getImplementation2(){
return impl2;
}
}
#Path("/servicename")
public class MyService {
#Inject
private RestService rs;
#POST
#Path("/compute")
public void compute(){
rs.execute(new Runnable(){
public void run(){
rs.getImplementation1().compute();
}
});
}
}
For option 1 I'm not sure about the "life cycle" about a static field. Which option should I use ? How would you do that ?
Thanks
EDIT :
Option 3 (thread handled by EJB Container) and "ordering" is not important :
#Singleton
public class RestService {
private final Executor executor;
private final Implementation1 impl1;
private final Implementation2 impl2;
public RestService () {
executor = Executors.newSingleThreadExecutor();
impl1 = new Implementation1();
impl2 = new Implementation2();
}
public void compute1(){
executor.execute(new Runnable(){
public void run(){
impl1.compute();
}
});
}
public void compute2(){
executor.execute(new Runnable(){
public void run(){
impl2.compute();
}
});
}
}
#Path("/servicename")
public class MyService {
#Inject
private RestService rs;
#POST
#Path("/compute1")
public void compute1(){
rs.compute1();
}
#POST
#Path("/compute2")
public void compute2(){
rs.compute2();
}
}
I think Option 3 is still better than Option 1 & 2.
I think it's a bad idea to do this. Threading ought to be handled by your container, not your code.
If you're deploying on a Java EE app server, you should let it handle the threading.
If you're deploying on a non-blocking I/O server like Netty or vert.x, you should let it handle the threading.
Under no circumstances should you be managing threads.
Static fields are instantiated when the .class loads. They don't have a "lifecycle" the way instances do. They won't be cleaned up until the class loader removes the .class file.
If you must have this kind of behavior, I'd either use a JMS queue to order the processing or a producer/consumer deque to manage it. You want the processing to be asynch. Let the REST service return a token or receipt to the client and have them come back to see when the processing is done. If the line is long, you'll have no way to know when their shirt is ready. The receipt lets them come back and check when their result is available.
If you used Spring, and then separated your business logic out into separate components (beans) and injected these beans into your service class you could effectively control the threading model of your implementation simply by changing the 'scope' attribute of your business logic beans.
Here's a description of Spring bean scopes.
This approach would allow you to easily modify/experiment with your solution and discover the best alternative for your situation.
As far as architecture is concerned I would recommend that you layer your system(loose coupling, high cohesion, separation of concerns, etc.). In this regard, you would probably have a service layer (REST), a business layer, and a data (dao) layer minimum. The layers interact with each other via interfaces. Use Spring to wire things together (inject dependencies). This gives you the flexibility to inject different implementations. Example would be to inject mock DAOs for your business classes for unit tests. The service layer where your REST services live would perform the translation of requests/responses, some validation, determine which business components to invoke, and invoke them.
Is it possible to use callbacks with Spring to that they are managed by application context?
My problem is when a service is used from outer by #Autowired, but within that service there is a callback defined using new operator.
The following example executes a method that is worth retrying. Spring offers a RetryCallback for this case (I know this could be acchieved differently, but just to illustrate my callback problem).
#Service
class MyService {
//main method invoked
void run(DataVO dataVO) {
//new operator not usable in spring context
RetryCallback<Object> retryCallback = new RetryCallback<Object>() {
#Override
public Object doWithRetry(RetryContext context) throws Exception {
return createBooking(dataVO);
}
};
}
private Object createBooking(DataVO dataVO) {
//creates the booking, worth retry on specific failures
//uses further injected/autowired services here
}
}
Is it possible to refactor this snippet so that the callback is managed by spring/injected/autowired?
Make your service implement the callback interface :
#Service
class MyService implements RetryCallback<Object> {
//main method invoked
void run(DataVO dataVO) {
}
#Override
public Object doWithRetry(RetryContext context) throws Exception {
return createBooking(dataVO);
}
private Object createBooking(DataVO dataVO) {
//creates the booking, worth retry on specific failures
//uses further injected/autowired services here
}
}