How do I utilize supportsNullCreation() in Jersey? - java

I have an injectable provider that may or may return null. I am getting an exception when it is null. I registered the provider as a Singleton, can I possibly register it as a type of SingletonContext that I customize to return true for supportsNullCreation()? I think if I can do that then even if findOrCreate() returns null, my code will still run which is what I want.
#ApplicationPath("rest")
public class MyApplication extends ResourceConfig
{
public MyApplication()
{
...
// Provider of DB
this.register( new AbstractBinder()
{
#Override
public void configure()
{
bindFactory(DbManager.class).to(EntityManagerFactory.class).in(Singleton.class);
}
});
}
Then it is used like this:
#Singleton
#Path("myservice")
public class WebServiceClass
{
// NOTE: Right now I have to comment this to run without a DB
#Inject
private EntityManagerFactory entityManagerFactory = null;
...
The exception I get is this...
java.lang.IllegalStateException: Context
org.jvnet.hk2.internal.SingletonContext#6cae5847 findOrCreate returned a null for
descriptor SystemDescriptor(
implementation=com.db.DbManager
contracts={javax.persistence.EntityManagerFactory}
scope=javax.inject.Singleton
qualifiers={}
descriptorType=PROVIDE_METHOD
descriptorVisibility=NORMAL
metadata=
rank=0
loader=org.glassfish.hk2.utilities.binding.AbstractBinder$2#7050f2b1
proxiable=null
proxyForSameScope=null
analysisName=null
id=145
locatorId=0
identityHashCode=863132354
reified=true)
at org.jvnet.hk2.internal.Utilities.createService(Utilities.java:2075)
...

I would recommend changing the design a bit. Using the EntityManagerFactory in the resource class is not very great design. You are left with code like
public class Resource {
private EntityManagerFctory emf;
#POST
public Response get(Entity e) {
EntityManager em = emf.createEntityManager();
em.getTransaction().begin();
em.persist(e);
em.getTransaction().commit();
em.close();
}
}
There are a lot of things wrong with this picture. For one you are breaking the [Single Responsibility Principle][1]. Secondly this doesn't allow you to elegantly handle the null EMF, even if it was possible. You have this all over the place
if (emf != null) {
// do code above
} else {
// do something else.
}
Also it is no great for testing. The common pattern is to use a DAO layer. Personally I even add a service layer in between the DAO and the REST layer, but you can get away with just a DAO layer.
For example what I would do is create a common abstraction interface for the data access calls.
public interface DataService {
Data getData();
}
Then create an implementation for db access
public class WithDbService implements DataService {
private EntityManagerFactory emf;
public WithDbService(EntityManagerFactory emf) {
this.emf = emf;
}
#Override
public Data getData() {
...
}
}
Then create another implementation without db access.
public class WithoutDbService implements DataService {
#Override
public Data getData() {}
}
Then you can use a Factory to create the DataService. What you will do is use the ServiceLocator to try and find the EMF. If it is not null, return the WithDbService else return the WithoutDbService
public class DataServiceFatory implements Factory<DataService> {
private DataService dataService;
#Inject
public DataServiceFactory(ServiceLocator locator) {
// abbreviated for brevity
EMF emf = locator.getService(EMF.class);
if (emf != null) {
dataService = new WithDbService(emf);
} else {
dataService = new WithoutDbService();
}
}
#Override
public DataService provider() { return dataService; }
}
[...]
bindFactory(DataServiceFactory.class).to(DataService.class).in(..);
Then you can just inject DataService every where. As long as the two implementations follow the contract, it should work just fine.
There may be some design improvements, but it is a big step up from using the EMF directly in the resource class.

Related

JPA EntityManager not working when using Guice's PrivateModule

I have a service with a persistence setup using JPA, Hibernate and Guice (if it's useful, I'm not using Spring). This is the first, working version of my code:
public class BookDao {
#Inject
protected Provider<EntityManager> entityManagerProvider;
protected EntityManager getEntityManager() {
return entityManagerProvider.get();
}
#Transactional
public void persist(Book book) {
getEntityManager().persist(book);
}
}
public class MyAppModule extends AbstractModule {
#Override
protected void configure() {
initializePersistence();
}
private void initializePersistence() {
final JpaPersistModule jpaPersistModule = new JpaPersistModule("prod");
jpaPersistModule.properties(new Properties());
install(jpaPersistModule);
}
}
But now I need to configure multiple persistence units. I'm following the advice in this mailing list, and according to them, I should move my module logic to a private module. I did as suggested and created a second version of the same code, the changes are commented below:
#BindingAnnotation
#Retention(RetentionPolicy.RUNTIME)
#Target({ FIELD, PARAMETER, METHOD })
public #interface ProductionDataSource {} // defined this new annotation
public class BookDao {
#Inject
#ProductionDataSource // added the annotation here
protected Provider<EntityManager> entityManagerProvider;
protected EntityManager getEntityManager() {
return entityManagerProvider.get();
}
#Transactional
public void persist(Book book) throws Exception {
getEntityManager().persist(book);
}
}
public class MyAppModule extends PrivateModule { // module is now private
#Override
protected void configure() {
initializePersistence();
// expose the annotated entity manager
Provider<EntityManager> entityManagerProvider = binder().getProvider(EntityManager.class);
bind(EntityManager.class).annotatedWith(ProductionDataSource.class).toProvider(entityManagerProvider);
expose(EntityManager.class).annotatedWith(ProductionDataSource.class);
}
private void initializePersistence() {
JpaPersistModule jpaPersistModule = new JpaPersistModule("prod");
jpaPersistModule.properties(new Properties());
install(jpaPersistModule);
}
}
The newly annotated EntityManager is being correctly injected by Guice and is non-null, but here's the fun part: some of my unit tests started failing, for example:
class BookDaoTest {
private Injector injector;
private BookDao testee;
#BeforeEach
public void setup() {
injector = Guice.createInjector(new MyAppModule());
injector.injectMembers(this);
testee = injector.getInstance(BookDao.class);
}
#Test
public void testPersistBook() throws Exception {
// given
Book newBook = new Book();
assertNull(newBook.getId());
// when
newBook = testee.persist(newBook);
// then
assertNotNull(newBook.getId()); // works in the first version, fails in the second
}
}
In the first version of my code the last line above just works: the entity is persisted and has a new id. However, in the second version of my code (using a PrivateModule and exposing an annotated EntityManager from it) the persist() operation doesn't work anymore, the entity is without an id. What could be the problem? I didn't do any other configuration changes in my environment, and I don't see error messages in the logs. Let me know if you need more details.
It turns out that the problem was the #Transactional annotation. In the first version of my code, Guice automatically adds interceptors for managing the transaction. By doing a debug, I found out that before executing my persist(Book book) method, Guice calls the following method from the com.google.inject.internal.InterceptorStackCallback package:
public Object intercept(Object proxy, Method method, Object[] arguments, MethodProxy methodProxy)
In the second version of my code, when I exposed the persistence unit from a private module the above interceptor was no longer called, leaving my persist operation without transaction handling. This is a known issue and is by design.
As a workaround I had to implement transactions by hand, making my code more verbose. I also had to change the way the entity manager is injected. This solution worked for me:
public class BookDao {
#Inject
#Named(PROD_PERSISTENCE_UNIT_NAME)
private EntityManagerFactory entityManagerFactory;
private EntityManager getEntityManager() {
return entityManagerFactory.createEntityManager();
}
public void persist(Book book) throws Exception {
EntityManager em = getEntityManager();
try {
em.getTransaction().begin();
em.persist(book);
em.getTransaction().commit();
} catch (Exception e) {
em.getTransaction().rollback();
throw e;
} finally {
em.close();
}
}
}
public class MyAppModule extends PrivateModule {
public static final String PROD_PERSISTENCE_UNIT_NAME = "prod";
#Override
protected void configure() {
initializePersistence();
}
private void initializePersistence() {
// persistence unit set to prod DB
final JpaPersistModule jpaPersistModule = new JpaPersistModule(PROD_PERSISTENCE_UNIT_NAME);
// connection properties set to suitable prod values
jpaPersistModule.properties(new Properties());
install(jpaPersistModule);
// expose bindings to entity manager annotated as "prod"
bind(JPAInitializer.class).asEagerSingleton();
bind(PersistService.class).annotatedWith(named(PROD_PERSISTENCE_UNIT_NAME)).to(PersistService.class).asEagerSingleton();
expose(PersistService.class).annotatedWith(named(PROD_PERSISTENCE_UNIT_NAME));
bind(EntityManagerFactory.class).annotatedWith(named(PROD_PERSISTENCE_UNIT_NAME)).toProvider(binder().getProvider(EntityManagerFactory.class));
expose(EntityManagerFactory.class).annotatedWith(named(PROD_PERSISTENCE_UNIT_NAME));
bind(EntityManager.class).annotatedWith(named(PROD_PERSISTENCE_UNIT_NAME)).toProvider(binder().getProvider(EntityManager.class));
expose(EntityManager.class).annotatedWith(named(PROD_PERSISTENCE_UNIT_NAME));
bind(UnitOfWork.class).annotatedWith(named(PROD_PERSISTENCE_UNIT_NAME)).toProvider(binder().getProvider(UnitOfWork.class));
expose(UnitOfWork.class).annotatedWith(named(PROD_PERSISTENCE_UNIT_NAME));
}
}
As a lesson, be very watchful around annotations and other such "magic" that modifies your code under the hood, finding bugs becomes quite difficult.

How are transactions used when I mix EJBs and CDI beans?

I'm working on a JEE application that only uses EJBs at the moment. The application processes messages and stores some things in the database and/or possibly sends messages to other applications (pretty straightforward I guess).
I have some filtering business logic that determines whether or not the data should be stored in a database. Something like this (simplified):
#MessageDriven(...)
public class MessageListener {
private FilterProvider filter = new FilterProvider();
#EJB private SomeDao dao;
public void handleMessage(SomeMessage message) {
if(filter.allows(message)) {
dao.store(message);
} else {
// Ignore, not relevant
}
}
}
#Stateless
#TransactionAttribute(TransactionAttributeType.REQUIRED)
public class SomeDao {
public store(SomeMessage message) {
// Create the right entities and store in the db
}
}
public class FilterProvider {
public boolean allows(SomeMessage message) {
return message.getAllowed() == true;
}
}
Currently I'm investigating if I can use CDI to inject the FilterProvider and I've put together these modifications:
#MessageDriven(...)
public class MessageListener {
#Inject
private FilterProvider filter; // <-- Added annotation here and removed constructor call.
#EJB private SomeDao dao;
public void handleMessage(SomeMessage message) {
if(filter.allows(message)) {
dao.store(message);
} else {
// Ignore, not relevant
}
}
}
#Stateless
#TransactionAttribute(TransactionAttributeType.REQUIRED)
public class SomeDao {
public store(SomeMessage message) {
// Create the right entities and store in the db
}
}
#Default // <-- Added annotation here
public class FilterProvider {
public boolean allows(SomeMessage message) {
return message.getAllowed() == true;
}
}
My first question: What is the impact on the transactions by these changes?
My second question: What kind of risks/pitfalls am I introducing by this type of setup?

Spring Entities Not Saved To Database

We have set up the Spring Framework like this:
#Eager
public interface CatalogElementRepository extends PagingAndSortingRepository<CatalogElementEntity, Long> {
}
#Service
public class CatalogImpl implements CatalogManager {
#Inject
CatalogElementRepository catalogElementRepository;
#Override
public CatalogElement createCatalogElement(CatalogElementEntity catalogElement) {
return this.catalogElementRepository.save(catalogElement);
}
}
#Stateless
#Remote(CatalogManager.class)
public class CatalogManagerBean implements CatalogManager {
#Inject
CatalogManager delegate;
#Override
public CatalogElement createCatalogElement(CatalogElementEntity catalogElement) {
return this.delegate.createCatalogElement(catalogElement);
}
}
So whenever someone calls the method on the remote interface createCatalogElement, I'd assume the entity gets stored in the database. It does not (weirdly enough, findOne still returns the very same entity, but it can't be found via findByProperty).
Other questions said to add #Transactional, so I added #javax.transaction.Transactional and org.springframework.transaction.annotation.Transactional on the methods and classes to be on the safe side, nothing worked.
What could be the problem?
I don't see any configuration files for the Spring Framework, but it's a legacy project, so they might just be hidden very well.
For some reason using this class as a producer for the EntityManager helped:
public class SpringConfig {
#PersistenceUnit
EntityManagerFactory emf;
#PersistenceContext
EntityManager em;
#Produces
#ApplicationScoped
public EntityManagerFactory createEntityManagerFactory() {
return this.emf;
}
#Produces
public EntityManager createEntityManager() {
return this.em;
}
public void close(#Disposes EntityManagerFactory entityManagerFactory) {
entityManagerFactory.close();
}
public void close(#Disposes EntityManager entityManager) {
entityManager.close();
}
}

Call spring inject class from a static method from another class

Well, i have a class with #Component anotation, this class makes some selects in database, see:
#Component(value = "parametroRelatorioHelper")
public class ParametroRelatorioHelper {
#Autowired
private BasicDAO dao;
public ParametroRelatorio getParametroByNome(String nome) {
List<ParametroRelatorio> parametros = (List<ParametroRelatorio>) dao
.findByNamedQuery(ParametroRelatorio.FIND_BY_NOME,
new NamedParams("nome", nome));
if (parametros.size() > 0)
return parametros.get(0);
else
return null;
}
public List<ParametroRelatorio> getAll() {
return (List<ParametroRelatorio>) dao
.findByNamedQuery(ParametroRelatorio.FIND_ALL);
}
public BasicDAO getDao() {
return dao;
}
public void setDao(BasicDAO dao) {
this.dao = dao;
}
}
Now, i have a "Helper" class, where user can call your method directly (static method) but i need call a method from ParametroRelatorioHelper, see:
public class ReportHelper {
public static void call(){
//how can i do it without #Component injection
parametroRelatorioHelper.getAll();
}
}
It sounds like your architecture is incorrect, instead the ReportHelper should be a component too and the dependencies should be injected in it, otherwise it collides with the idea of the Spring IOC, helper methods should not rely on components on services...

HibernateUtil with JPA

I can't figure out what HibernateUtil is ...
Is it required with JPA?
I use JPA with GWT , is this implementation sufficient?
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;
public final class EMF {
private static final EntityManagerFactory emfInstance =
Persistence.createEntityManagerFactory("default");
private EMF() {}
public static EntityManagerFactory get() {
return emfInstance;
}
}
And at the use:
public class AccountDao {
public static final EntityManager entityManager() {
return Emf.get().createEntityManager();
}
public void createAccount(Account account) {
EntityManager em = entityManager();
EntityTransaction tx = em.getTransaction();
try {
tx.begin();
em.persist(account);
tx.commit();
}
catch (Throwable t) {
t.printStackTrace();
tx.rollback();
}
finally {
em.close();
}
}
}
See this post (Gilead JPA configuration) please. I can't understand yet, how to use HibernateUtil, or HibernateJpaUtil, or PersistentBeanManager stuff ...
To use Gilead with GWT, first change your GWT-RPC service implementations from
public class MyServiceImpl extends RemoteServiceServlet implements MyService {
....
}
into:
public class MyServiceImpl extends PersistentRemoteService implements MyService {
....
}
Then, in the constructor of these classes, call the method setBeanManager(beanManager). Perform the setup as I described in my other answer. Here's the entire code snippet for reference:
public class MyServiceImpl extends PersistentRemoteService implements MyService {
public MyServiceImpl() {
EntityManagerFactory emf = EMF.get();
HibernateJpaUtil hibernateJpaUtil = new HibernateJpaUtil();
hibernateJpaUtil.setEntityManagerFactory(emf);
PersistentBeanManager persistentBeanManager =
GwtConfigurationHelper.initGwtStatelessBeanManager(hibernateJpaUtil);
setBeanManager(persistentBeanManager);
}
// Service methods follow here
}
This is sufficient for the setup - Gilead then uses the bean manager (and HibernateJpaUtils) automatically under the covers, you don't have to interact directly with it. All you have to do is to make sure, that your entities extend net.sf.gilead.pojo.gwt.LightEntity.
Your implementation is pretty sufficient. I would put the factory in the servlet context, rather than making it static though.
But note an important thing here. The above code will work if you are using it purely on the server-side.
Since you are using GWT, it is possible (although I don't think it is rational) to use hibernate "stuff" on the client-side. For that you'd need gilead, where you will need the forementioned utilities.

Categories

Resources