I have a pure JAVA project, which I develop in eclipse with maven. It has a persistence capability using JPA with EclipseLink that save the data into Apache Derby. The project workts perfectly in unit tests and in standalone java applications, in which I instantiate the EntityManagerFactory directly from my code:
public class JPAUtil
{
private static EntityManagerFactory factory = Persistence.createEntityManagerFactory("unit-name");
private static Map<Long, EntityManager> ems = new HashMap<Long, EntityManager>();
private JPAUtil(){}
/**
* Get an entity manager
*/
public static EntityManager em(Long id)
{
EntityManager result = null;
if (ems.containsKey(id))
{
result = ems.get(id);
if(!result.isOpen())
{
result = createEntityManager();
ems.put(id, result);
}
}
else
{
result = createEntityManager();
ems.put(id, result);
}
return result;
}
private static EntityManager createEntityManager()
{
EntityManager result =
// factory.createEntityManager(SynchronizationType.SYNCHRONIZED);
factory.createEntityManager();
return result;
}
}
Now when I add it into a GWT project I am hitting some very difficult to debug/solve problems.
Problem 1:
If I use the above JPAUtil class to instantiate EntityManagers for use on each RPC request it works. However, if the GWT client-side started making multiple requests to the server-side, which in turn tried to pull data from the JPA layer, multiple cryptic ConcurrencyException occured on read (with or without lazy loading - it seems to make no difference).
When instead of using the above class I try to "inject" the EntityManager using the following lines into the GWT ServiceImpls (servlets), attempting to access the data layer crashes with a NullPointerException:
#PersistenceContext(unitName = "unit-name")
transient protected EntityManager em;
I obviously was thinking, that it would be a more appropriate way of accessing the persistence layer from GWT. However, I get NullPointerExceptions when accessing the EntityManager, ergo the development Jetty server of GWT cannot inject the EntityManager by itself. My skills with this kind of problems appear to be limited, and my Google-FU seems to be helpless either. So to formulate a concrete question:
How would it be best to approach the problem of creating a fast, stable GWT application with JPA in the backend?
Thank you in advance,
el.nicko
You need to synchronize your access to the HashMap as many RPC requests can be handled in parallel by multiple threads. Suggest you replace HashMap with ConcurrentHashMap or put synchronize on the em method.
#Inject will likely not work as GWT servlet is not CDI aware.
Related
I am currently creating a Vaadin app that is supposed to get it's content data from a mysql database on a server (e.g. server run with Xampp). The problem is I am confused with a direction that most information sources give me. Every single tutorial has spring and spring boot code and there is no actual reference to creating a connection with data base in vaadin. I read a lot about the matter but still all that comes up are spring backends with some vaadin UI elements. Does it mean that Vaadin app uses spring components for connection with data base and updating, showing, editing the data using vaadin UI forms etc? I'm really confused right now. So then what is the difference between creating app in Vaadin or spring/spring boot if the back-end is still created in spring no matter what?
Vaadin does not take any decisions about how the data is accessed. If you are using spring-boot then creating data source according to their documentation would be a good place to start.
Now you are set to create entities and repositories. You can then edit and display entities in Vaadin application. Some recommend creating separate classes for editing and viewing while others don't.
Each Vaadin page that you have could, for example, have injected repository which it uses to load entities that it will then present to the user.
As Mika said, Vaadin does not decide your CMS connection. I recommend using Vaadin and hibernate since you can use dataproviders and hibernate criteria for easy filtering of data.
EDIT: Code-Example (really just an example)
I recommend you read about Hibernate and DataProviders yourself
public class EntityDataProvider extends AbstractDataProvider<Entity, Filter> implements DataProvider<CarePiDevice, String> {
private static final long serialVersionUID = 7331161527158310247L;
private SessionFactory sessionFactory;
public EntityDataProvider() {
Configuration configuration = new Configuration().configure();
sessionFactory = configuration.buildSessionFactory();
}
#Override
public boolean isInMemory() {
return false;
}
#Override
public int size(#Nullable Query<Entity, Filter> query) {
Session session = sessionFactory.openSession();
Criteria criteria = session.createCriteria(Entity.class);
Filter filter = query.getFilter();
// apply filters to Criteria
return criteria.list().size();
}
#Override
public Stream<CarePiDevice> fetch(#Nullable Query<Entity, Filter> query) {
Session session = sessionFactory.openSession();
Criteria criteria = session.createCriteria(Entity.class);
Filter filter = query.getFilter();
// apply filters to Criteria
return criteria.list().stream();
}
}
Let's say there are #Service and #Repository interfaces like the following:
#Repository
public interface OrderDao extends JpaRepository<Order, Integer> {
}
public interface OrderService {
void saveOrder(Order order);
}
#Service
public class OrderServiceImpl implements OrderService {
#Autowired
private OrderDao orderDao;
#Override
#Transactional
public void saveOrder(Order order) {
orderDao.save(order);
}
}
This is part of working application, everything is configured to access single database and everything works fine.
Now, I would like to have possibility to create stand-alone working instance of OrderService with auto-wired OrderDao using pure Java with jdbcUrl specified in Java code, something like this:
final int tenantId = 3578;
final String jdbcUrl = "jdbc:mysql://localhost:3306/database_" + tenantId;
OrderService orderService = someMethodWithSpringMagic(appContext, jdbcUrl);
As you can see I would like to introduce multi-tenant architecture with tenant per database strategy to existing Spring-based application.
Please note that I was able to achieve that quite easily before with self-implemented jdbcTemplate-like logic also with JDBC transactions correctly working so this is very valid task.
Please also note that I need quite simple transaction logic to start transaction, do several requests in service method in scope of that transaction and then commit it/rollback on exception.
Most solutions on the web regarding multi-tenancy with Spring propose specifying concrete persistence units in xml config AND/OR using annotation-based configuration which is highly inflexible because in order to add new database url whole application should be stopped, xml config/annotation code should be changed and application started.
So, basically I'm looking for a piece of code which is able to create #Service just like Spring creates it internally after properties are read from XML configs / annotations. I'm also looking into using ProxyBeanFactory for that, because Spring uses AOP to create service instances (so I guess simple good-old re-usable OOP is not the way to go here).
Is Spring flexible enough to allow this relatively simple case of code reuse?
Any hints will be greatly appreciated and if I find complete answer to this question I'll post it here for future generations :)
HIbernate has out of the box support for multi tenancy, check that out before trying your own. Hibernate requires a MultiTenantConnectionProvider and CurrentTenantIdentifierResolver for which there are default implementations out of the box but you can always write your own implementation. If it is only a schema change it is actually pretty simple to implement (execute a query before returning the connection). Else hold a map of datasources and get an instance from that, or create a new instance.
About 8 years ago we already wrote a generic solution which was documented here and the code is here. It isn't specific for hibernate and could be used with basically anything you need to switch around. We used it for DataSources and also some web related things (theming amongst others).
Creating a transactional proxy for an annotated service is not a difficult task but I'm not sure that you really need it. To choose a database for a tenantId I guess that you only need to concentrate in DataSource interface.
For example, with a simple driver managed datasource:
public class MultitenancyDriverManagerDataSource extends DriverManagerDataSource {
#Override
protected Connection getConnectionFromDriverManager(String url,
Properties props) throws SQLException {
Integer tenant = MultitenancyContext.getTenantId();
if (tenant != null)
url += "_" + tenant;
return super.getConnectionFromDriverManager(url, props);
}
}
public class MultitenancyContext {
private static ThreadLocal<Integer> tenant = new ThreadLocal<Integer>();
public static Integer getTenantId() {
return tenant.get();
}
public static void setTenatId(Integer value) {
tenant.set(value);
}
}
Of course, If you want to use a connection pool, you need to elaborate it a bit, for example using a connection pool per tenant.
I am developing a JavaEE6 based web application using JBoss7.
In my application I am injecting the EntityManager in my EJBs as:
class ForumServiceEJB
{
#PersistenceContext(type=EXTENDED)
private EntityManager em;
}
class TopicServiceEJB
{
#PersistenceContext(type=EXTENDED)
private EntityManager em;
}
The problem when I update some data using ForumServiceEJB's EntityManager then the changes are made into DB but TopicServiceEJB's EntityManager is not able to see those changes and the results are always fetched from Cache.
I am using ExtendedPerssisteenceContext as My Entities contain child Entity Collections of Lazy Loading type.
How can I use/Inject EntityManager of type ExtendedPersistenceContext and make different EntityManager in one EJB can still see the changes done by other different EJB EntityManagers?
Somewhere I read EntityManagers should be RequestScoped objects.
public class MyEntityManagerProducers {
#Produces #RequestScoped
public EntityManager createDbEm() {
return Persistence.createEntityManagerFactory("forumDb").
createEntityManager();
}
public void disposeUdEm(#Disposes EntityManager em) {
em.close();
}
Is it the way to go?
I am using ExtendedPerssisteenceContext as My Entities contain child
Entity Collections of Lazy Loading type.
This is not a good reason to use EXTENDED. I would suggest you to make it default, which is TRANSACTION. And it's good to make your EntityManager request-scoped, or method-scoped, in non-enterprise environment or when using application-managed persistence, as this is not a very heavy object to create. Moreover, neither using application-scoped EntityManager is a good idea, as it is not threadsafe.
Having said that, as you are using JBoss, you should let the container handle the lifecycle of EntityManager, in case you are using JTA. Hence, just inject that with everything default
Note:
Only stateful session beans can have a container-managed, extended entity manager.
Links:
http://javanotepad.blogspot.com/2007/08/managing-jpa-entitymanager-lifecycle.html
https://blogs.oracle.com/enterprisetechtips/entry/extended_persistence_context_in_stateful
Suggestions:
Your business method should know whether to load the children or not. But that's the ideal case. A number of times we can't say that and completely depends on the user input -- we can't predict that well. Therefore, there are two solutions available,
make a separate AJAX call to load children
Use the filter called open-session-in-view. I would prefer the former.
Links:
https://community.jboss.org/wiki/OpenSessionInView
http://static.springsource.org/spring/docs/1.2.9/api/org/springframework/orm/hibernate3/support/OpenSessionInViewFilter.html
Why is Hibernate Open Session in View considered a bad practice?
The #Multitenant support in Eclipselink 2.3 looks really interesting, but I'm having a hard time understanding how to use it in a JSF or EJB which injects an EntityManager with #PersistenceContext. The EclipseLink docs are pretty clear that #PersistenceContext injection doesn't work in this case, but you could inject an EntityManagerFactory via #PersistenceUunit instead.
Still, what I'm not seeing is how to manage the lifecycle of an EntityManager you might create via injected EntityManagerFactory.createEntityManager() - in particular, when to close the resulting EntityManager, and how to participate in transactions.
Has anyone gotten this to work? Or am I missing something obvious?
See also: http://wiki.eclipse.org/EclipseLink/Examples/JPA/Multitenant
UPDATE
I had some success with #PersistenceContext (EntityManager) injection and then passing parameters to EclipseLink via session listener. I'm not 100% sure this is the right answer and would appreciate confirmation that it isn't creating a non-obvious race condition or thread-safety issue.
For example:
public static class TenantListener extends SessionEventAdapter {
#Override
public void postAcquireClientSession(SessionEvent event) {
long tenantId = **business logic**;
event.getSession().setProperty("eclipselink.tenant-id", tenantId);
}
}
Using events is fine.
You could also inject the EntityManager and set the property, or inject the EntityManagerFactory and use joinTransaction() to join the active JTA transaction.
It is continues of question ( struts 2 bean is not created )
I'm using struts2 + toplink in my very simple web application under Tomcat.
On the page I would like use iteration tag. That is why I've declared some factory (SomeFactory) that resolves collection of entities (Entity).
Per article: http://download-uk.oracle.com/docs/cd/B32110_01/web.1013/b28221/usclient005.htm#CIHCEHHG
the only thing I need is declaration:
#PersistenceContext(unitName="name_in_persistence_xml")
public class SomeFactory
{
#PersistenceUnit(unitName="name_in_persistence_xml")
EntityManagerFactory emf;
public EntityManager getEntityManager() {
assert(emf != null); //HERE every time it is null
return emf.createEntityManager();
}
public Collection<Entity> getAll()
{
return getEntityManager().createNamedQuery("Entity.findAll").getResultList();
}
}
What is wrong? May be i miss something in web.xml? How to pre-init toplink for web application to allow injection happen?
You won't get anything injected by Tomcat which is not a Java EE container (and even with a Java EE 5 container, injection only works for managed components like servlets, filters, listeners, EJB, web service endpoints...). So you will have to create the EntityManagerFactory manually (typically in a servlet or a helper class) and get the EntityManager from it:
EntityManagerFactory emf = Persistence.createEntityManagerFactory(PU_NAME);
EntityManager entityManager = emf.createEntityManager();
Note that creating an EntityManagerFactory is a costly operation and should not be done for each request. However, creating an EntityManager is not and you should get one for each thread. But in your case, I'd suggest to use the struts2-persistenceplugin to handle this.
Thanks, but it seems [...] that Java EE is not mandatory to use injection [...] the Spring brings necessary engine for it.
Indeed. But you wrote "NO spring at all" in your other question and you didn't list any piece that could provide injection out of the box. Anyway, check out the struts2-persistenceplugin, it might be enough for your needs.