Update injected domain object in Java EE 7 CDI Application - java

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!

Related

Session replication with VaadinSession not working

We have a web application that is using Spring Boot (1.5) with Vaadin (7.7), and is using Apache Shiro (1.4.0) for security.
The application is configured to use DefaultWebSessionManager to let Shiro handle the session management instead of the servlet container.
We are using the official Vaadin Spring integration (1.2.0), and after some configuration it all works as intended. The VaadinSession contains a wrapped ShiroHttpSession internally.
We want to achieve session replication, by configuring Shiro to use a SessionDAO that is backed by an external Cache, which means the sessions get (de)serialized.
As soon as we start using this SessionDAO, Vaadin will crash and stop working. When replace the external cache by an in memory Map for the sake of debugging, it works again.
It seems this is caused by the SpringVaadinServlet, as it stores the VaadinSession as a session attribute. VaadinSession is Serializable and the Javadoc shows:
Everything inside a VaadinSession should be serializable to ensure
compatibility with schemes using serialization for persisting the
session data.
Inside the VaadinSession are some fields that are not Serializable, for example a Lock and the wrapped http session inside is also marked as transient.
Because of this, the session that Vaadin uses will be broken as soon as it is distributed, resulting in a lot of crashes.
So it turns out the VaadinSession is not actually usable in session replication? Why is this and how can we work around this?
Note: we also have a version of the application that is using Vaadin 8, and here the same thing happens. It seems that the issue is caused by the Vaadin Spring integration.
Inside the VaadinSession are some fields that are not Serializable, for example a Lock and the wrapped http session inside is also marked as transient.
The wrapped http session is not part of Vaadin session, it is the the http session. Thus it is transient. The same can be said about Lock, whose instance is stored in the http session.
In order to implement session serialization correctly, you need to hook into serialization events and update the transients when session is being deserialized. VaadinSession should be loaded with VaadinService#loadSession, which calls VaadinSession#refreshTransients.
Everything inside a VaadinSession should be serializable to ensure compatibility with schemes using serialization for persisting the session data.
This statement does not imply that you can serialize your application out of the box. It just means, that in case your application is serializable as well, with careful engineering you can serialize the whole thing.
For example Vaadin is not updating the session attribute in each possible occasion for performance reasons. There is method VaadinService#storeSession for that. So you need to either override right method or setup request filter. E.g. you could do this at VaadinService#endRequest.
Note, you need to use sticky sessions in order to get this to work with moderate amount of effort. If your session is de-serialized in different machine, the re-entrant lock instances wont be valid. If you would like to be able to de-serialize the session in different machine, it would require that your infrastructure can offer distributed lock that you can use instead of re-entrant Lock of Java and override Vaadin's getSessionLock and setSessionLock methods to use that.
Valuable sources of further info:
Generic notes from Vaadin's CTO
https://vaadin.com/blog/session-replication-in-the-world-of-vaadin
Testimonial from developer who did it with one stack
https://vaadin.com/learn/tutorials/hazelcast
Thoughts from another senior developer
https://mvysny.github.io/vaadin-14-session-replication/

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.

Managing database transactions manually in a Spring/Hibernate environment

We've got a Spring based web application that makes use of Hibernate to load/store its entities to the underlying database.
Since it's a backend application we not only want to allow our UI but also 3rd party tools to manually initiate DB transactions. That's why the callers need to
Call a StartTransaction method and in return get an ID that they can refer to
Do all DB relevant calls (e. g. creating, modifying, deleting) by referring to this ID to make clear which operations belong to the started transaction
Call the CommitTransaction method to signal to our backend that the transaction can be committed now (or in the negative case RollbackTransaction will be called)
So keeping in mind, that all database handling will be done internally by the Java persistence annotations, how can we open the transaction management to our UI that behaves like a 3rd party application that has no direct access to the backend entities but deals with data transfer objects only?
From the Spring Reference: Programmatic transaction management
I think this can be done but would be a royal pain to implement/verify. You would basically require a transaction manager which is not bounded by "per-thread-transaction" definition but spans across multiple invocations for the same client.
JTA + Stateful session beans might be something you would want to have a look at.
Why don't you build services around your 'back end application' for example a SOAP interface or a REST interface.
With this strategy you can manage your transaction in the backend

Making sense of JPA and EJB3 and WebServices

I'm just getting started with JPA, creating stateless session beans from the JPA entities, then accessing the beans through a web service. While I have a lot of experience developing database backed web services "the old way", I have some questions about what's going on behind the scenes with this new "annotation driven approach".
What I see is, NetBeans sort of directs you to build applications in this manner though their wizards.
Create an Enterprise Application with EJB and Web Application modules.
Create Entity classes. I created mine from an existing database.
Create session beans from the entity class.
Create Web services from the session bean.
It all looks pretty simple, but what's going on behind the scenes? Specifically:
I see that the web service (created with the #WebService annotation) references my stateless session bean (using the #EJB reference).
What happens here? Does it just grab an instance of the EJB from the application server's EJB pool?
Nevermind. I was thinking of an instance where there was more than 1 table - meaning more than 1 type of Entity class and more than 1 type of EJB. I was looking at the web service and just seeing the #EJB reference and didn't understand who it was getting the bean type from that annotation. Just below that however, it the reference to the local bean interface - so that's that.
If there is more than 1 type of EJB deployed to the server, how does it know which one to grab?
The EJB is defined via the #Stateless and #Local annotations. The bean implementation references an EnityManager via the #PersistenceContext annotation.
Where is the jndi lookup to the database done (maybe in the persistence.xml file)?
Do all of the EJBs share a common EntityManager (assuming the EntityManager is thread safe)? If not, I know that the EnityManager utilizes a second level cache to help reduce trips to the database, are these caches somehow kept in sync?
I know this is a lot of questions, but they're all sort of related and there seem to be a lot of complicated concepts for something that's so easy to build through the wizards. I want to make sure I understand what's all going on here.
Thanks in advance!
What happens here? Does it just grab an instance of the EJB from the application server's EJB pool?
A JAX-WS web component endpoint (as opposed to a JAX-WS EJB endpoint) follows the typical servlet threading model, which means that typically there is one instance that is executed concurrently for each client. JAX-WS implementations are free to leverage pools of bean instances to handle a request in a fashion similar to stateless session EJB components. (source: Developing Applications for the JavaTM EE Platform FJ-310).
In all cases, it is fine to inject/look-up stateless beans because the container guarantees that the beans will always be thread safe. In affect, the container automatically serializes clients calls but uses instance pooling to make sure you still get concurrency benefits.
If there is more than 1 EJB deployed to the server, how does it know which one to grab?
Hmm... I didn't get this one. Can you clarify what you mean exactly? Why would there be any ambiguity?
Where is the jndi lookup to the database done (maybe in the persistence.xml file)?
In a Java EE environment, you specify your data source in a <jta-data-source> element in each persistence unit of the persistence.xml file (which can contain several persistence units) and the data source will be obtained by the EntityManager (only when needed, i.e. only if a data access is really needed).
Do all of the EJBs share a common EntityManager?
No. The EntityManager is a non-thread-safe object that should be used once, for a single business process, a single unit of work, and then discarded. In a Java EE environment using EJB 3, the default pattern is "entitymanager-per-request". A request from the client is send to the EJB 3 persistence layer, a new EntityManager is opened, and all database operations are executed in this unit of work. Once the work has been completed (and the response for the client has been prepared), the persistence context is flushed and closed, as well as the entity manager object. (source: Chapter 4. Transactions and Concurrency).

Ejb 3, message driven bean cooperating with a stateful session bean?

Hey! I'm relative new to both Java EE and Stackowerflow, please be kind :-)
I have a bunch of devices triggering Java messages to be sent on any state change. These devices are typically active for about 30-90 minute intervals. Each event message contains a device id in addition to the event details.
Central in my application is a message driven bean subscribing to those events. Every time I get an event I have to hit the database to look up some info about the device.
It would be absolutely terrific if I could associate a stateful session bean with each active device! If this had been a web application I would have used the http session to store a handle or reference to the stateful bean (I'm I right?). Is there any way that I can archive this from my message bean?
It would be nice, except it can't be done like you explained. MDBs (and SLSBs) are stateless by definition so it's safe to keep a conversation only during the invocation.
You could eventually break the spec and create a static attribute somewhere (maybe in the MDB itself) but this would certainly be not portable, neither scalable.
My suggestion is to enable caching at the JPA level (see your persistence provider of preference for details), so you can lookup whatever data you need very fast (really fast). This is portable and cluster-friendly. That's the way I use to do it in my projects and I am very happy with it.
Hope it helps.
I'm not that comfortable recommending specific products, but isn't the Terracotta server adressing needs like this?

Categories

Resources