Remote polling in ManagedBean and notify client-view via push - jsf

I have a jsf view which shows some data from a managed-bean (viewscope) in a table, that is retrieved remotely.
Currently the data is updated via polling from the client-view using primefaces poll component.
This is not sufficient enough, since to much traffic is sent to client and now that primefaces supports server-push I only want to reload the data and push it to the client-view if data has been changed.
This should be realized via polling from the web-tier to application tier calling a method like hasChanged(...). If data is changed the web-tier pushes a notification to client to reload data.
Current client poll
client >> web-tier >> app-tier
client asks web-tier via ajax for data which again asks app-tier for data and updates view
Wished web-tier poll and push
client << web-tier >> app-tier
web-tier polls app-tier if data has changed and reloads on behalf and informs (pushes) client to update view
Approaches:
What is the best approach to realize the polling at the managed-bean in the web-tier?
TimerTask in the managed-bean
Spawning threads in a JSF managed bean for scheduled tasks using a timer
Additional EJB with Schedule annotation
Additional EJB with TimerService
other?
Edit:
Architecture: (3-tier)
Server1: database
Server2: app-tier (EAR with Remote EJB + Hibernate)
Server3: web-tier (WAR with JSF 2.0 + Primefaces 3.4)
Client: Browser

Based on my experience, I can recommend two routes, Spring Integration and CDI Events. I'd recommend the Spring route, but based on your current stack, I think CDI events have you covered. They cleanly help you achieve the Observer/Observable pattern and you can pull of a clean separation of tiers too. I must warn you though, this approach is effective only for a small-medium use case. Consider the following:
Design and implement an Event class that encapsulates all the information that is required to be delivered to consumers. Let's call it a FundsTransfer event Your event implementation should contain enough information to enable listeners filter only for events of interest.
A simple POJO
class FundsTransfer {
BigDecimal transferValue;
Date transferDate;
int transferCurrencyCode;
public FundsTransfer(BigDecimal transferValue, Date date, int currencyCode) {
//set accordingly
}
//setters and getters
}
Implement a business object at the business layer, call it Notifier. The function of polling should be delegated to this object. It will be in charge of creating and publishing objects of type event in response to changes on the server side. Depending on your requirements, this object could be a singleton to handle all Event types or you could have a group of Notifier types polling for different events.
//A sample implementation of your Observer object :
#Singleton //Defines a singleton EJB
public class PollerService {
#Inject
Event fundsTranferNotifier;
//this annotation specifies that the polling method should run every second.
#Schedule(second = "*/1", minute = "*", hour = "*", persistent = false)
public void pollIt() {
boolean found = this.pollingMethod(); // pollingMethod() will do the actual polling
if (found) { //based on the outcome of the polling method, fire the notifier method
blowWhistleOnTransfer();
}
}
public void blowWhistleOnTransfer() {
//this is the broadcast event.
fundsTransferNotifier.fire(new FundsTransfer(new BigDecimal("100000", new Date(), 855));
}
}
In the code above, I've used a Timer EJB as my Observer. See this for an introduction to EJB timers. Again, the Observer object will live in the app tier
The client tier will each have access to an listener object that will be notified when an event of interest occurs (that is has been published by a Notifier type). Then the listener can issue a push based on this event. Your listener object could be a POJO with #Named CDI annotation. In your listener object, simply implement a method with an #Observes annotation, with a parameter of the type of event the listener is interested in:
public void onNewTransfer(#Observes FundsTransfer transfer) {
if (transfer.compareTo(new BigDecimal("150000")) > 0) {
//push to view.
}
}
The above filtering is still quite crude compared to the message filtering options that CDI provides. As you can see from the tutorial I referenced earlier, you could create CDI qualifiers that can give you finer grained filtering on messages. Like I stated earlier, this is a bit heavy for large scale deployment, in which case I'd advise the spring integration route, if you're up to take the dependency on.
In summary, the model of the system will be:
One Poller(Notifier) Object (In the app layer)
|
|
|
Multiple Listener Objects (In the web tier)
---------------------------------------------------
| | | | | | | | | | | |

Related

Spring Boot Rest-Controller restrict multithreading

I want my Rest Controller POST Endpoint to only allow one thread to execute the method and every other thread shall get 429 until the first thread is finished.
#ResponseStatus(code = HttpStatus.CREATED)
#PostMapping(value ="/myApp",consumes="application/json",produces="application/json")
public Execution execute(#RequestBody ParameterDTO StartDateParameter)
{
if(StartDateParameter.getStartDate()==null) {
throw new ResponseStatusException(HttpStatus.BAD_REQUEST);
}else {
if(Executer.isProcessAlive()) {
throw new ResponseStatusException(HttpStatus.TOO_MANY_REQUESTS);
}else {
return Executer.execute(StartDateParameter);
}
}
}
When I send multithreaded requests, every request gets 201. So I think the requests get in earlier than the isAlive() method beeing checked. How can I change it to only process the first request and "block" every other?
Lifecycle of a controller in spring is managed by the container and by default, it is singleton, which means that there is one instance of the bean created at startup and multiple threads can use it. The only way you can make it single threaded is if you use a synchronized block or handle the request call through an Executor service. But that defeats the entire purpose of using spring framework.
Spring provides other means to make your code thread safe. You can use the #Scope annotation to override the default scope. Since you are using a RestController, you could use the "request" scope (#Scope("request")), which creates a new instance to process your every http request. Doing it this way will make ensure that only 1 thread will be accessing your controller code at any given time.

IMediatr with Autofac in Domain Objects DDD

I have set my Domain Model objects to be independent of any service and infrastructure logic.
I am also using Domain Events to react to some changes in Domain Models.
Now my problem is how to raise those events from the Domain Model objects itself.
Currently I am using Udi Dahan's DomainEvents static class for this (I need evens to be handled exactly when they happen and not at a latter time).
The events are used for many things, like logging, updating the data in related services and other Domain Model objects and db, publishing messages to the MassTransit bus etc.
The DomainEvents static class uses Autofac scope that I inject at some point in it, to find the IMediatr instance and to publish the events, like this:
public static class DomainEvents
{
private static ILifetimeScope Scope;
public async static Task RaiseAsync<TDomainEvent>(TDomainEvent #event) where TDomainEvent : IDomainEvent
{
var mediator = Scope?.Resolve<IMediatorBus>();
if (mediator != null)
{
await mediator!.Publish(#event).ConfigureAwait(false);
}
else
{
Debug.WriteLine("Mediator not set for DomainEvents!");
}
}
public static void SetScope(ILifetimeScope scope)
{
Scope = scope;
}
}
This all works ok in a single-threaded environment, but the method DomainEvents.SetScope() is a possible racing problem in multhi-threaded environment.
Ie. When I introduce MassTransit and create message consumers, each Message consumer will set the current LifetimeScope to DomainEvents by that method, and here is the problem, each consumer will overwrite the lifetime scope with the new one.
Why I use DomainEvents static class? Because I don't want to pollute my Domain Model Objects with infrastructure stuff.
I thought about making DomainEvents non static (define an interface), but then I need them injected in every Domain Model Object and I'm still thinking about this, but maybe there is a better way.
I want to know if there is a better way to handle this?
Maybe some change in DomainEvents class? Or maybe remove the DomainEvents static class end use an interface or DomainService to do this.
The problem is I don't like static classes, but I also don't like pushing non domain-specific dependencies into Domain Model Objects.
Please help.
UPDATE
To better clarify the process and for what I use DomainEvents...
I have a long-running process that can take from few minutes to few hours/days to complete.
So the process is going like this:
I receive an message from MassTransit ie ProcessStartMessage(processId)
Get the ProcessData for (processId) from Db.
Construct an in-memory Domain Model ProcessTracker (singleton) and put all the data I loaded from DB in it. (in-memory cache)
I receive another message from Masstransit ie. ProcessStatusChanged(processId, data).
Forward this message data to in-memory singleton ProcessTracker to process.
ProcessTracker process the data.
For ProcessTracker to be able to process this data it instantiates many Domain Model Objects, each responsible to process some part of the data. (Note there is NO more db calls and entity hydration from db, it all happens in memory, also Domain Model is not mapped to any entity, it is not connected to any db object).
At some point I need to log what a Domain Model object in the chain has done, has it work finished or started, has reached some milestone etc. This is done by raising DomainEvents. I also need to notify the GUI of those events, so they are used to send Masstransit messages too.
Ie.(pseudo code):
public class ProcessTracker
{
private Step _currentStep;
public void ProcessData(data)
{
_currentStep.ProcessData(data);
DomainEvents.Raise(new ProcesTrackerDataProcessed());
...
}
}
public class Step
{
public Phase _currentPhase;
public void ProcessData(data)
{
if (data.IsManual && _someOtherCondition())
{
DomainEvents.Raise(new StepDataEvent1());
...
}
if(data.CanTransition)
{
DomainEvents.Raise(new TransitionToNewPhase(this, data));
}
_currentPhase.DoSomeWork(data);
DomainEvents.Raise(new StepDataProcessed(this, data));
...
}
}
About db updates, those are not transactional and not important to the process and the Domain Model Object state is kept only in memory, if the process crash the process MUST begin from the start (there is NO recovery).
To end the process:
I receive ProcessEnd from the MassTransit
The message data is forwarded to the ProcessTracker
ProcessTracker handles the data an nets a result of the proceess
The result of the process is saved to db
A message is sent to other parties in the process that notifies them of a process completion.
Ask yourself first what are you going to do when you raise an event from your domain model?
Normally it works like this:
Get a command
Load a domain object from a repository
Execute behaviour
(here probably) Raise an event
Persist the new domain object state
So, where your extra domain event handlers would fit? Are you going to execute some other database calls, send an email? Remember that it all happens now, when you haven't even persisted the changed state of your domain object. What if your persistence fails? It will happen after you executed all the domain handlers.
You should not execute more than one transaction when you handle a single command. The Aggregate pattern clearly tells you that the aggregate is the transaction boundary. You should raise domain events after you complete the transaction, or within the same technical transaction, but it should only persist the aggregate state and the event. Domain event reactions potentially trigger transactions for other domain objects, and it should be done outside of the scope of handling the current command.
The issue is not at all technical, it is a design problem.
If you use MassTransit, you can only make it (relatively) reliable if you handle the command in a message consumer. Then, you can use in-memory outbox, which will not send an event unless the consumer succeeded. It is still not guaranteed that the event will be published in case of the broker failure.
Unless you go to Event Sourcing, you have two 100% reliable options:
Use a transactional outbox pattern (NServiceBus has one and it's quite complex). It has limitations on what type of database you use.
Store the event to the same database as the domain object, in a different table, within the same transaction. Poll the table with DELETE INTO and emit events to the broker from there.

Quarkus Transactions on different thread

I have a quarkus application with an async endpoint that creates an entity with default properties, starts a new thread within the request method and executes a long running job and then returns the entity as a response for the client to track.
#POST
#Transactional
public Response startJob(#NonNull JsonObject request) {
// create my entity
JobsRecord job = new JobsRecord();
// set default properties
job.setName(request.getString("name"));
// make persistent
jobsRepository.persist(job);
// start the long running job on a different thread
Executor.execute(() -> longRunning(job));
return Response.accepted().entity(job).build();
}
Additionally, the long running job will make updates to the entity as it runs and so it must also be transactional. However, the database entity just doesn't get updated.
These are the issues I am facing:
I get the following warnings:
ARJUNA012094: Commit of action id 0:ffffc0a80065:f2db:5ef4e1c7:0 invoked while multiple threads active within it.
ARJUNA012107: CheckedAction::check - atomic action 0:ffffc0a80065:f2db:5ef4e1c7:0 commiting with 2 threads active!
Seems like something that should be avoided.
I tried using #Transaction(value = TxType.REQUIRES_NEW) to no avail.
I tried using the API Approach instead of the #Transactional approach on longRunning as mentioned in the guide as follows:
#Inject UserTransaction transaction;
.
.
.
try {
transaction.begin();
jobsRecord.setStatus("Complete");
jobsRecord.setCompletedOn(new Timestamp(System.currentTimeMillis()));
transaction.commit();
} catch (Exception e) {
e.printStackTrace();
transaction.rollback();
}
but then I get the errors: ARJUNA016051: thread is already associated with a transaction! and ARJUNA016079: Transaction rollback status is:ActionStatus.COMMITTED
I tried both the declarative and API based methods again this time with context propagation enabled. But still no luck.
Finally, based on the third approach, I thought keeping the #Transactional on the Http request handler and leaving longRunning as is without declarative or API based transaction approaches would work. However the database still does not get updated.
Clearly I am misunderstanding how JTA and context propagation works (among other things).
Is there a way (or even a design pattern) that allows me to update database entities asynchronously in a quarkus web application? Also why wouldn't any of the approaches I took have any effect?
Using quarkus 1.4.1.Final with ext: [agroal, cdi, flyway, hibernate-orm, hibernate-orm-panache, hibernate-validator, kubernetes-client, mutiny, narayana-jta, rest-client, resteasy, resteasy-jackson, resteasy-mutiny, smallrye-context-propagation, smallrye-health, smallrye-openapi, swagger-ui]
You should return an async type from your JAX-RS resource method, the transaction context will then be available when the async stage executes. There is some relevant documentation in the quarkus guide on context propagation.
I would start by looking at the one of the reactive examples such as the getting started quickstart. Try annotating each resource endpoint with #Transactional and the async code will run with a transaction context.

CDI multithreading

We want to optimize our application. There is some streight linear work going on, that can be executed in multiple threads with smaller working sets.
Our typical service is accessed using the #Inject annotation from within our CDI-managed beans. Also such a service could have it's own dependencies injected, i.e.:
public class MyService {
#Inject
private OtherService otherService;
#Inject
private DataService1 dataService1;
...
public void doSomething() {
...
}
}
Because I can not use #Inject inside the class implementing Runnable. (It's not container managed.) I tried to pass the required services to the class before starting the thread. So, using something like this, makes the service instance (myService) available within the thread:
Class Thread1 implements Runnable{
private MyService myService
public Thread1(MyService myService){
this.myService = myService;
}
public void run(){
myService.doSomething();
}
}
Following the call-hierarchy the call to doStometing() is fine, because a reference to myService has been passed. As far as I understand CDI, the injection is done the moment the attribute is accessed for the first time, meaning, when the doStomething() method tries to access either otherService or dataService1, the injection would be performed.
At that point however I receive an exception, that there is no context available.
I also tried to use the JBossThreadExecuter class instead of Plain-Threads - it leads to the very same result.
So the question would be, if there is a nice way to associate a context (or request) with a created Thread?
For EJB-Beans, I read that marking a method with #Asynchronous will cause the method to be run in a managed thread which itself will be wired to the context. That would basically be exactly what I'm searching for.
Is there a way to do this in CDI?
Or is there any way to obtain a context from within a unmanaged thread?
Weld allows programmatic context management, (there's an example in the official docs).
But before you go this way give EJBs a chance )
#Async invocation functionality is there exactly for your case. And as a bonus you'll get timeout interception and transaction management.
When you kick off an async process, your #RequestScoped and #SessionScoped objects are no longer in scope. That's why you get resolution errors for the injected #RequestScoped objects. Using #Stateless without a CDI scope is essentially #Dependent. You can use #ApplicationScoped objects or if you're on CDI 1.1 you can start up #TransactionScoped.
You have to use JavaEE 7 feature, the managed executor. So it will provide a context for your runnable. I'm not sure if your JBoss version is JavaEE 7 compatible. At least Glassfish 4 is, and that approach works.
See details here
Easiest Solution one can think of is Ejb Async.
They are powerful, does the job and most importantly the concurrency is handled by the container(which could be an issue at some point of time if its not properly managed).
Just a simple use case lets say if we have written a rest service and each request spawns 10 threads(ex using CompletableFuture or anything) to do some long processing tasks and for an instance if 500 requests are made then how will the threads be managed, how the app behaves, does it waits for a thread from the thread pool, what is the timeout period, etc etc and to add to our comfort what happens when the threads are Deamon Threads. We can avoid these overheads to some extent using EJBs.
Its always a good thing to have a friend from the technical services team to help us with all these container specific implementations.

Hibernate Session Threading

I have a problem regarding Hibernate and lazy loading.
Background:
I have a Spring MVC web app, I use Hibernate for my persistence layer. I'm using OpenSessionInViewFilter to enable me to lazy load entities in my view layer. And I'm extending the HibernateDaoSupport classes and using HibernateTemplate to save/load objects. Everything has been working quite well. Up until now.
The Problem:
I have a task which can be started via a web request. When the request is routed to a controller, the controller will create a new Runnable for this task and start the thread to run the task. So the original thread will return and the Hibernate session which was put in ThreadLocal (by OpenSessionInViewFilter) is not available to the new thread for the Task. So when the task does some database stuff I get the infamous LazyInitializationException.
Can any one suggest the best way I can make a Hibernate session available to the Task?
Thanks for reading.
Make your Runnable a Spring bean and add #Transactional annotation over run. You must be warned thou that this asynchronous task won't run in the same transaction as your web request.
And please don't start new thread, use pooling/executor.
Here is a working example on how to use the Hibernate session inside a Runnable:
#Service
#Transactional
public class ScheduleService {
#Autowired
private SessionFactory sessionFactory;
#Autowired
private ThreadPoolTaskScheduler scheduler;
public void doSomething() {
ScheduledFuture sf = scheduler.schedule(new Runnable() {
#Override
public void run() {
SpringBeanAutowiringSupport.processInjectionBasedOnCurrentContext(scheduler);
final Session session = sessionFactory.openSession();
// Now you can use the session
}
}, new CronTrigger("25 8 * * * *"));
}
}
SpringBeanAutowiringSupport.processInjectionBasedOnCurrentContext() takes a reference to any Spring managed bean, so the scheduler itself is fine. Any other Spring managed bean would work as well.
Do I understand correctly, you want to perform some action in a completely dedicated background thread, right? In that case, I recommend you not accessing the Hibernates OpenSessionInViewFilter and further session logic for that thread at all, because it will, is you correctly noted, run in a decoupled thread and therefore information loaded in the original thread (i.e, the one that dealt with the initial HttpRequest). I think it would be wise to open and close the session yourself within that thread.
Otherwise, you might question why you are running that operation in a separated thread. May be it is sufficient to run the operation normally and present the user with some 'loading' screen in the meantime?

Resources