Expose current progress of an #Asynchronous function to use in View - java

In my JEE6-App (running on Glassfish 3.0.1) I have an EmailEJB which has to send lots of mails. The mails are sent asynchronously, so its annotated with the new EJB3.1 #Asynchronous, letting it be run in a separate Thread. Now i want the user to be informed about the current status of the method: How many mails have already been sent?
Sending the mails asynchronously works fine, but i can't figure out how to let the progress be accessible from outside. Seems like my approach to do that is quite wrong, but somehow it has to be possible (maybe another approach). This is how my EmailEJB currently looks like (its kind of pseudo code, but explains what i want):
#Stateful
public class EmailEJB {
#Asynchronous
public Future<Integer> sendMails() {
for (int i=0; i<mails.size; i++) {
sendMail(mails[i])
// i want to return the progress without returning ;)
return new AsyncResult<Integer>(i)
}
}
}
//Just for the completeness... from outside, i'm accessing the progress like this:
Future<Integer> progress = emailEJB.sendEmails();
Integer currentvalue = progress.get();
How can i return the current progress inside my asynchronous function, without cancelling it with a return? How can i show the user the progress of a loop inside a function? Do i need another asynchronous method? Any hints?

Nobody? Ok so this is my solution. Im not sure if this is a big fat workaround or just a way to get this done.
Since an #Asynchronous method cannot access the Session context, and therefore also no Session Beans (at least i dont know how, i always got ConcurrentModificationErrors or similar ones) i created a Singleton ProgressEJB, which contains a HashMap:
#Singleton #LocalBean #Startup
public class ProgressEJB {
private HashMap<String, Integer> progressMap = new HashMap<String, Integer>
// getters and setters
}
This hashmap should map the SessionId (a String) to an Integer value (the progress 0->100). So a user session is associated with a progress.
In my EmailEJB, i'm injecting this ProgressEJB, and in my #Asynchronous method, i'm increasing the value everytime an email has been sent:
#Stateful #LocalBean
public class EmailEJB {
#Inject
private ProgressEJB progress;
// Mail-Settings
...
#Asynchronous
public void sendEmails(user:User, message:Message, sessionId:String) {
progress.progressMap.put(sessionId, 0);
for (int i=0; i<mails.size; i++) {
sendMail(mails[i])
progress.getProgressMap().put(sessionId, (i / mails.size) * 100)
}
progress.getProgressMap().remove(sessionId);
}
The sessionId comes from my Managed (Weld) Bean, when calling the function:
#SessionScoped
#Named
public class EmailManager {
#Inject
private ProgressEJB progress;
#Inject
private FacesContext facesContext;
private String sessionId;
#PostConstruct
private void setSessionId() {
this.sessionId = ((HttpSession)facesContext.getExternalContext().getSession(false)).getId();
}
public Integer getProgress() {
if (progress.getProgressMap().get(sessionId) == null)
return 100;
else
return progress.getProgressMap().get(sessionId);
}
}
Now i can access progress from EmailManager from my JSF view with Ajax Polling, telling the user how many mails already have been sent. Just tested it with 2 users, seems to work.

I also see only a #Singleton solution here.
But this imply the need of Housekeeping in ProgressEJB. E.g. some effort is needed to prune old session from Hashmap.

Another solution is described in
Is there any way to know the progress of a EJB Asynchronous process?
This solution does not need a Stateful Bean.
#Stateless
public class EmailEJB {
// Mail-Settings
...
#Asynchronous
public void sendEmails(User user, Message message, WorkContext context) {
progress.progressMap.put(sessionId, 0);
for (int i=0; i<mails.size; i++) {
sendMail(mails[i])
context.setProgress((i / mails.size) * 100)
}
context.setRunning(false);
}
}
The Context-Object, which holds the progress.
public class WorkContext {
//volatile is important!
private volatile Integer progress = 0;
private volatile boolean running = false;
// getters & setters
}
The usage is very easy.
#SessionScoped
#Named
public class EmailManager {
#Inject
private EmailEJB emailEJB;
private WorkContext workContext;
public void doStuff() {
workContext = new WorkContext();
emailEJB.sendEmails(user, message, workContext)
}
public Integer getProgress() {
return workContext.getProgress();
}
....
}

Related

How can I make a Java Spring Component class thread safe?

I have a spring class that when you call httpDatastoreFacade.getDatastore() it should give you the REST request thread safe datastore:
#Component
public class HttpDatastoreFacade {
private Boolean useAttribute = Boolean.FALSE;
public String getDatastore() {
HttpServletRequest request = ((ServletRequestAttributes)RequestContextholder.currentRequestAttributes()).getRequest();
String datastore = request.getParameter("datastore");
if(useAttribute) {
datastore = String.valueOf(request.getAttribute("datastore"));
}
return datastore;
}
public void setDatastore(String datastore, Boolean useAttribute) {
HttpServletRequest request = ((ServletRequestAttributes)RequestContextholder.currentRequestAttributes()).getRequest();
request.setAttribute("datastore", datastore);
this.useAttribute = useAttribute;
}
public Boolean getUseAttribute() {
return useAttribute;
}
}
Sometimes in my code I need to change that datastore but then I want to immediately change it back after I call whatever code needs the datastore differently:
#Component
public class someClass() {
#Autowired
private HttpDatastoreFacade datastoreFacade;
#Autowired
private OtherClass otherClass;
public void someMethod() {
String savedDatastore = datastoreFacade.getDatastore();
String savedUseAttribute = datastoreFacade.getUseAttribute;
//setDatastore to new settings
datastoreFacade.setDatastore("newStore", true);
//this is where I call my method's or methods that need this new datastore
otherClass.callSomeMethod();
//set the datastore back to old value
datastoreFacade.setDatastore(savedDatastore , savedUseAttribute );
}
}
My issue is that I'm running into threading problems where useAttribute is true but the datastore isn't set in the request attribute.
I'm looking for a better java pattern where I can lock the HttpDatastoreFacade while I do my otherClass.callSomeMethod() or whatever other calls I need to make until I set the HttpDatastoreFacade back to normal. otherCalss.callSomeMethod may be calling other methods that use HttpDatastoreFacade as well and they may want to set it how they need it. So maybe I need some short of datastore stack that is thread safe?
Seems a bean in #RequestScope could solve your problem.
#Component
#RequestScope
public class X {
//
}
you won't have to think about clearing the request scoped bean as you would the ThreadLocal. It will be collected when the corresponding ServletRequest is cleaned up.
I ended up making useAttribute a ThreadLocal variable which solved my problems.
private ThreadLocal<Boolean> useAttribute = new ThreadLocal<>();

How to create some sort of event framework in java?

I don't have a GUI (my classes are part of a Minecraft Mod). I wanted to be able to mimic C# event framework: A class declares events and lets others subscribe to them.
My first approach was to create a class called EventArgs and then do something like this:
public class EventArgs
{
public boolean handled;
}
#FunctionalInterface
public interface IEventHandler<TEvtArgs extends EventArgs>
{
public void handle(Object source, TEvtArgs args);
}
public class Event<TEvtArgs extends EventArgs>
{
private final Object owner;
private final LinkedList<IEventHandler<TEvtArgs>> handlers = new LinkedList<>();
public Event(Object owner)
{
this.owner = owner;
}
public void subscribe(IEventHandler<TEvtArgs> handler)
{
handlers.add(handler);
}
public void unsubscribe(IEventHandler<TEvtArgs> handler)
{
while(handlers.remove(handler));
}
public void raise(TEvtArgs args)
{
for(IEventHandler<TEvtArgs> handler : handlers)
{
handler.handle(owner, args);
if(args.handled)
break;
}
}
}
Then a class would do something like this:
public class PropertyChangedEvtArgs extends EventArgs
{
public final Object oldValue;
public final Object newValue;
public PropertyChangedEvtArgs(final Object oldValue, final Object newValue)
{
this.oldValue = oldValue;
this.newValue = newValue;
}
}
public class SomeEventPublisher
{
private int property = 0;
private final Random rnd = new Random();
public final Event<PropertyChangedEvtArgs> PropertyChanged = new Event<>(this);
public void raiseEventOrNot(int value)
{
if(rnd.nextBoolean())//just to represent the fact that the event is not always raised
{
int old = property;
property = value;
PropertyChanged.raise(new PropertyChangedEvtArgs("old(" + old + ")", "new(" + value + ")"));
}
}
}
public class SomeSubscriber
{
private final SomeEventPublisher eventPublisher = new SomeEventPublisher();
public SomeSubscriber()
{
eventPublisher.PropertyChanged.subscribe(this::handlePropertyAChanges);
}
private void handlePropertyAChanges(Object source, PropertyChangedEvtArgs args)
{
System.out.println("old:" + args.oldValue);
System.out.println("new:" + args.newValue + "\n");
}
public void someMethod(int i)
{
eventPublisher.raiseEventOrNot(i);
}
}
public class Main
{
private static final SomeSubscriber subscriber = new SomeSubscriber();
public static void main(String[] args)
{
for(int i = 0; i < 10; ++i)
{
subscriber.someMethod(i);
}
}
}
The biggest problem with this naïve approach is that it breaks proper encapsullation by exposing raise as public. I can't see a way around it, and maybe my whole pattern is wrong. I would like some ideas.
There's also a related problem: I would like the events to be raised immediately after the method raising them returns. Is there a way to synchronize this using threads or some other construct? The caller code, of course, can't be involved in the task of synchronization. It has to be completely transparent to it.
The best thing to do here is to avoid implementing your own event framework in the first place, and instead rely on some existing library. Out of the box Java provides EventListener, and at a minimum you can follow the patterns documented there. Even for non-GUI applications most of this advice applies.
Going beyond the JDK Guava provides several possible options, depending on your exact use case.
The most likely candidate is EventBus, which:
allows publish-subscribe-style communication between components without requiring the components to explicitly register with one another (and thus be aware of each other).
Or ListenableFuture (and ListeningExecutorService) which:
allows you to register callbacks to be executed once [a task submitted to an Executor] is complete, or if the computation is already complete, immediately. This simple addition makes it possible to efficiently support many operations that the basic Future interface cannot support.
Or the Service API which:
represents an object with an operational state, with methods to start and stop. For example, webservers, RPC servers, and timers can implement the Service interface. Managing the state of services like these, which require proper startup and shutdown management, can be nontrivial, especially if multiple threads or scheduling is involved.
This API similarly lets you register listeners to respond to state changes in your services.
Even if none of these options directly work for your use case, take a look at Guava's source code for examples of event-driven behavior and listeners you can try to emulate.

Using the provider from two different scopes

I have the following problem with Guice: a singleton service, is injected with provider of context-sensitive information. Until now, context was related only to servlet requests, so I used a #RequestScoped provider, and I was injecting this provider in service like so:
#RequestScoped
public class ContextProvider<IContext> implements Provider<IContext> {
#Override
public IContext get() { ... } // returns context
}
#Singleton
public class ServiceImpl implements IService {
#Inject
private Provider<IContext> contextProvider;
}
That works fine. Now, I'm working on adding background task processing to the application. Background tasks are not initiated from web-requests, so I can not use ServletScopes.scopeRequest(..). I have written a custom scope (almost exact copy of BatchScoped from Giuce doc) to make each Task run in it's own scope. Now the question is - how to make BatchScoped ContextProvider and configure Guice to use it?
I've made this attempt with binding EDSL:
line 1 : bind(IContext.class).toProvider(ContextProvider.class).in(RequestScoped.class);
line 2 : bind(IContext.class).toProvider(BatchContextProvider.class).in(BatchScoped.class);
but Guice tells me at line 2 that 'A binding to IContext was already configured at line 1'.
The question is: what's the right way of doing such injection with Guice?
A similar question: Getting multiple guice singletons of the same type
In general the problem here is that you want to bind the same class to two different providers (and scopes, but that's actually beside the point). That is only possible if you use unique binding annotations for each one, like so:
bind(IContext.class)
.annotatedWith(MyAnnotation1.class)
.toProvider(ContextProvider.class)
.in(RequestScoped.class);
bind(IContext.class)
.annotatedWith(MyAnnotation2.class)
.toProvider(BatchContextProvider.class)
.in(BatchScoped.class);
And change injection sites to include relevant annotation:
#Inject
#MyAnnotationX
private Provider<IContext> contextProvider;
You need a fake request that starts with your background task and remains for all of it. That is what ServletScopes.scopeRequest does.
public class MyBackgroundTask extends Thread {
#Override
public void run() {
RequestScoper scope = ServletScopes.scopeRequest(Collections.emptyMap());
try ( RequestScoper.CloseableScope ignored = scope.open() ) {
doTask();
}
}
private void doTask() {
}
}
Oh, don't forget to use providers so you delay the retrieval of your dependencies. For example, expading the previous example so the background task uses your IContext.
public class MyBackgroundTask extends Thread {
private Provider<IContext> contextProvider;
#Inject
public MyBackgroundTask(Provider<IContext> contextProvider) {
this.contextProvider = contextProvider;
}
#Override
public void run() {
RequestScoper scope = ServletScopes.scopeRequest(Collections.emptyMap());
try ( RequestScoper.CloseableScope ignored = scope.open() ) {
doTask();
}
}
private void doTask() {
}
}
If you don't use providers the injection, in this example, will be done from the thread that creates the background task which could be inside another scope.
BONUS: You may have noticed the empty map sent as a parameter to the scopeRequest method. Check the Guice javadocs. Those are the instances that you want already present in your fake request scope. Depending on your IContext you may need it.

what's a good pattern for registering a Class to execute a specific task later on?

I'm writing a test suite, and I'm thinking about how to mock certain request/response flows. For example, I want to test a method that makes multiple RESTful calls:
getCounts() {
...
Promise<Integer> count1 = getCount1();
Promise<Integer> count2 = getCount2();
// returns a DataModel containing all counts when the Promises redeem
}
getCount1() {
...
Request<Foo> request = new Request<Foo>();
sendRequest(request);
...
}
getCount2() {
...
Request<Bar> request = new Request<Bar>();
sendRequest(request);
...
}
sendRequest(Request<T> request) {...}
However, each getCount() method creates a different Request<T> object, where <T> describes the type of request being made in regards to the count being retrieved. This means I can't simply "mock" the sendRequest() method since it is being called with a different type each time.
I was thinking about an approach where I register a "handler"... when sendRequest() is called, it determines which handler to call, and the handler would know the appropriate type of mock data to return. The registration would be something like storing the handler class type or an instance of the handler class along with the mock data it needs, and when sendRequest() is called, it would look for and invoke the correct handler.
However, I'm not sure if this a good pattern, and I'm wondering if there is a better way of approaching this problem. What is a good pattern for registering a Class or a particular method to execute a specific task later on?
Hard to answer without more context, but the general approach is to use Inversion Of Control (IOC). For example, put the getCountXXX methods into a class of their own, which may be a good idea for better reuse, readability, encapsulation, testability, etc:
public class CountFetcher {
getCount1() { ... }
getCount2() { ... }
}
The original code now gets an instance of CountFetcher using whatever "injection" mechanism is available to you. Simplest is just a constructor:
public class Counter {
private final CountFetcher fetcher;
public Counter(CountFetcher fetcher) {
this.fetcher = fetcher;
}
public getCounts() {
Promise<Integer> count1 = fetcher.getCount1();
Promise<Integer> count2 = fetcher.getCount2();
...
}
}
In your production code, you instantiate Counter with a real CountFetcher. In test code, you inject a mock version of CountFetcher which can have each individual getCountXXX method return whatever you want:
public class MockCountFetcher extends CountFetcher {
#Override
getCount1() { return mockCount1; }
}
public class TestCounter {
#Test
public void smokeTest() {
CountFetcher mockFetcher = new MockCountFetcher();
Counter counter = new Counter(mockFetcher);
assertEquals(someExpectedValue, counter.getCounts());
}
}

private method inside spring mvc controller is thread safe

As i understand spring mvc controllers are thread safe by default (like servlets). But I just want to know any private helper methods inside the controllers are thread safe ?
I have two mapping in the controller class eg: /test and test/success. Every time user invokes this url I want to check the user status and activation time in the database using a service method ( two different calls ). So I have decided to create a one private helper method to check the status.
So could anyone know that my private method is thread safe ?
All request are handled by one instance of your controller (singleton because it's a spring managed bean). So you need to make sure to not store any state (in a field) related to one request.
So:
#Controller
#RequestMapping("/foo")
public class Foo {
#Autowired
private Something something;
#RequestMapping("/list")
public String foo() {
something.someMethod();
bar();
return "view"
}
private void bar() {
// something
}
}
is OK, but:
#Controller
#RequestMapping("/foo")
public class Foo {
private User theUser; // problem is ALL request share this field
#RequestMapping("/foo/{userId}")
public String foo(#PathVariable final Integer userId) {
if (theUser.getId().equals(userId)) {
// something
} else {
theUser = ...
}
return "view"
}
}
is not.
NB: not tested (typed just here so it can even hurts your compiler)

Categories