CDI producer method for data model - java

I'd like to be able to #Inject a data model backing a RichFaces 4 ExtendedDataTable, but it requires an EntityManager to do its work. The EntityManager's queries need to know the Class, of course, and I'd rather not pass that into method calls (in this case the methods are not called by my code); ideally it would be in the constructor.
Something like this:
public class DataModel<T> {
#Inject private EntityManager em;
private Class<T> entityClass;
public DataModel(Class<T> entityClass) {
this.entityClass = entityClass;
}
//Sample method - this class will handle much more complex queries
public T findEntity(String key) {
return em.find(entityClass, key);
}
Is it possible to create a CDI #Producer that can be used to inject this DataModel into my backing beans? I've thought about making a Qualifier so you can do something like
#Inject #JType(value = MyEntity.class) DataModel<MyEntity> dataModel;
But that seemed clumsy, and would also require my #Producer to call new() - which I think would not allow the EntityManager to be injected into the DataModel. Also I'm not sure how you would require the qualifier to be added by the developer.
Or perhaps there's a better way to approach this, and I'm missing something?

I do this using the seam-persistence module from seam3. :
Producer :
public class EntityManagerProducer {
#Produces
#ExtensionManaged
#ConversationScoped
#PersistenceUnit(unitName = "yourUnitName")
private EntityManagerFactory emf;
}
Then you can #Inject the entity manager.
Otherwise, there is the DeltaSpike project that seems promising (never used it yet)

Related

Stateless Factory with EJB

I have a requirement to get pdf documents from my system. I'm using Apache Fop for this - and this library is using 2 files to generate pdf - xsl file with structure and styling and xml with data. So I'm getting xsl file from web resources, but now I need to generate xml with data from database. I tried this solution:
I have this interface:
public interface PrintableDocument {
Object getJaxBOjbect(Long personId);
}
That's one of the stateless bean to get object, I need 10 more beans like this to get different data for different documents.
#Stateless
#PrintableDocumentOneQualifier
public class PrintableDocumentOne implements PrintableDocument {
#Inject
private SomeRepository repository;
public Object getJaxBOjbect(Long personId) {
// Getting information from database
// formulating Object with data and returning it
}
}
So now I want to create Factory like this one:
#Stateless
#LocalBean
public class PrintableDocumentsFactory {
#Inject
#PrintableDocumentOneQualifier
private PrintableDocument printableDocumentOne;
#Inject
#PrintableDocumentTwoQualifier
private PrintableDocument printableDocumentTwo;
private Map<String, PrintableDocument> map = new HashMap<>();
#PostConstruct
public void init() {
map.put("one", printableDocumentOne);
map.put("two", printableDocumentTwo);
}
public PrintableDocument getPrintableDocument(String type) {
return map.get(type);
}
}
And on the service bean I want to use this factory:
#Stateless
#Local(DocumentService.class)
public class DocumentServiceBean {
#Inject
private PrintableDocumentsFactory factory;
public byte[] getPdf(InputStream xsl, Long id, String type) {
PrintableDocument printableDocument =
factory.getPrintableDocument(type);
Object jaxBOject = printableDocument.getJaxBObject(id);
//Use this object to get pdf and return it to web controller.
}
}
But now I'm getting null from getPrintableDocument from factory. I think the problem is that I need stateless beans, and they are getting picked back to EJB container, when getPrintableDocument method ends. So my question is: how can I manage this kind of situation?
EDIT 1: Missed PostConstruct annotation on init in Factory. Fixed that, still have the problem.
EDIT 2: If I will have #Singleton on my Factory will it hold just one by one instances of stateless PrintableDocument beans or it will return pooled instances instead? Because now I have to refill strategy holder map on factory when system will need another been to answer the request.
You could try to use #EJB instead of #Inject to inject the PrintableDocumentsFactory into your DocumentServiceBean.
Try adding a #PostConstruct annotation to PrintableDocumentsFactory.init() method. Currently the init method won't be called, so no get registered in the map.

How to configure providers with custom parameters?

My class depends on some services which needs to take few parameters and then make network call, currently I am passing those parameters and then creating those services via a factory injected into my class. I need to inject those services as a dependency instead, I know that I can create providers for them but in most of the examples I see that the providers are often bound to the fixed values like serveraddres etc. but I need to give then values during run time.
Below is my example code:
public SomeClass {
private final SomeFactory someFactory;
#Inject
SomeClass(SomeFactory factory) {
someFactory = factory;
}
public Foo getFoo(String fooId) {
FooService fooService = someFactory.getFooService(fooId);
return fooService.getFoo();
}
}
What I need to do is:
public SomeClass {
private final FooService fooService;
#Inject
SomeClass(FooService fooService) {
this.fooService = fooService;
}
public Foo getFoo(String fooId) {
return fooService.getFoo();
}
}
Update 1
Making the use case more clear:
#Provides
#RequestScoped
public SomeService provideSomeService(Dep1 dep1, String code) throws IOException {
return new SomeService.Builder()
.withApplicationName("Foo")
.setCode(code)
.build();
}
Here, code can be null by default and when needed I can give some value in it.
Can I somehow pass arguments to the provider before its created?
If you have a binding for your value (here, code is a String without a binding annotation), then your Update 1 is exactly what the code would look like.
In practice, there are a few differences:
Constants like int and String values are generally annotated with a binding annotation, either #Named or a custom annotation.
If you need to inject a value into an object graph after Guice initialization, but have a deep enough object graph that dependency injection is still a good idea, you can create a child injector. This way you can make a #Named("code") String accessible within one action or object, but not across your entire Guice application.
If your value for code is dynamic enough that it can't be provided through Guice as a key of its own, then you'll have to pass it in using a factory of some sort. For a Builder-based object, I'd say that your SomeFactory implementation is the best that I would come up with in your case.
If you don't need to use a Builder, and can let Guice create the object based on your fields or constructor parameters, you can code-generate a Factory.
Guice can generate a factory for you through FactoryModuleBuilder, in a feature known as "assisted injection".
Google's other tool, AutoFactory, will code-generate a factory implementation that works in both Guice and Dagger. (It's bundled as "Auto", which includes a model object generator called AutoValue that also generates annotation implementations.)
I put a small demonstration of a child injector and assisted injection in my other SO answer here.
The best approach here is to parameterize the module and pass the parameter through to a provider that you create at runtime:
public class MyModule extends AbstractModule {
private final String code;
public MyModule(String code) {
this.code = code;
}
#Override public void configure() {
Provider<Dep1> depProvider = getProvider(Dep1.class);
bind(SomeService.class)
.toProvider(() -> new SomeService.Builder()
.withApplicationName("Foo")
.withDep(depProvider.get())
.setCode(code)
.build())
.in(RequestScoped.class);
}
}

Producers with parameter injection?

How can I create a producer method that creates an object depending on a parameter?
My goal is to being able to inject a CrudService on different classes in my application, but to parametrize it with the class for which the service is used for (eg. User.class).
The following code does of course not work, but illustrates my intention.
#Produces
#JPAContainer(Class type) //something like this?
public JPAContainer getJPA() {
#PersistenceContext
private EntityManager em;
#Produces
#JPAContainerAnnot
public JPAContainer getJPAContainer() {
return JPAContainerFactory.make(type, em); //eg: class = User.class, Person.class
}
}
#Stateless
public class CrudServiceUser() {
#Inject
#JPAContainer(type = User.class) //something like this parameter
private JPAContainer container;
}
#Qualifier
#Retention(RetentionPolicy.RUNTIME)
#Target({FIELD,METHOD,PARAMETER,TYPE})
public #interface JPAContainer {
}
Yes, you can inject the InjectionPoint object in to your producer method. the type attribute of your qualifier needs to be #Nonbinding. From the InjectionPoint you can get reference to the annotations on the injection point, find your JPAContainer and read the values from it.

Please explain the #Produces annotation in CDI

I have read about the #Produces annotation in CDI, but I don't understand its usage.
public class Resources {
// Expose an entity manager using the resource producer pattern
#SuppressWarnings("unused")
#PersistenceContext
#Produces
private EntityManager em; //
#Produces
Logger getLogger(InjectionPoint ip) { //
String category = ip.getMember()
.getDeclaringClass()
.getName();
return Logger.getLogger(category);
}
#Produces
FacesContext getFacesContext() { //
return FacesContext.getCurrentInstance();
}
}
taken from: http://www.jboss.org/jdf/quickstarts/jboss-as-quickstart/guide/GreeterQuickstart/#GreeterQuickstart-
How does the container know to call a producer method? If I inject an EntityManager, how does the container call the #produces EntityManager? And how would a getLogger producer method get called?
I also don't see the reason to go through all of the trouble.
Section 3.3 of the CDI specification gives a pretty good high level overview of the use of the #Produces annotation:
A producer method acts as a source of objects to be injected, where:
• the objects to be injected are not required to be instances of beans, or
• the concrete type of the objects to be injected may vary at runtime, or
• the objects require some custom initialization that is not performed by the bean constructor.
Let's say, for example, that you wanted to bridge between a Java EE managed component like an entity manager and other CDI components, you could utilize the #Produces annotation. Another benefit being that you avoid having to duplicate #PersistenceContext annotations throughout your data domain layer.
class A {
#PersistenceContext // This is a JPA annotation
#Produces // This is a CDI 'hook'
private EntityManager em;
}
class B {
#Inject // Now we can inject an entity manager
private EntityManager em;
}
Another handy use is for getting around libraries that do not have CDI friendly beans (for example, no default constructors):
class SomeTPLClass {
public SomeTPLClass(String id) {
}
}
class SomeTPLClassProducer {
#Produces
public SomeTPLClass getInstance() {
return new SomeTPLClass("");
}
}
The Javadoc for produces also shows an interesting (but fairly rare case) of producing a named collection that can later on be injected into other managed beans (very cool):
public class Shop {
#Produces #ApplicationScoped
#Catalog #Named("catalog")
private List<Product> products = new LinkedList<Product>(8);
//...
}
public class OrderProcessor {
#Inject
#Catalog
private List<Product> products;
}
The container is responsible for processing all methods and fields marked with a #Produces annotation, and will normally do this when your application is deployed. The processed methods and fields will then be used as part of the injection point resolution for managed beans, as needed.
The example didn't quite work for me. What dit work was a minor tweak:
#Alternative
class SomeTPLClass {
public SomeTPLClass(String id) {
}
}
class SomeTPLClassProducer {
#Produces
public SomeTPLClass getInstance() {
return new SomeTPLClass("");
}
}
So i had to add #Alternative on my class to get rid of the error that there were two options for #Default.

Different ways of getting the EntityManager

The usual idiom I see for creating the EntityManager is something like this:
public class BaseDao {
private static final String PERSISTENCE_UNIT_NAME = "Employee";
EntityManagerFactory factory = Persistence.createEntityManagerFactory(PERSISTENCE_UNIT_NAME);
public EntityManager getEntityManager() {
return factory.createEntityManager();
}
}
Then it is used like this:
Employee emp = new Employee();
emp.setName("Joe M");
getEntityManager().persist(emp);
Question is why not do it this way:
public class BaseDao{
private static final String PERSISTENCE_UNIT_NAME = "Employee";
EntityManagerFactory factory = Persistence.createEntityManagerFactory(PERSISTENCE_UNIT_NAME);
private EntityManager entityManager = null;
public void setEntityManger() {
EntityManagerFactory factory = Persistence.createEntityManagerFactory(PERSISTENCE_UNIT_NAME);
this.entityManager = factory.createEntityManager();
}
public EntityManager getEntityManager() {
return this.entityManager;
}
}
In other words is there a need to always get the entity manager through factory.createEntityManager()? or can it be created as an instance (or even static) variable and retrieved like that?
To clarify, I am talking about an environment that doesn't use EJB or Spring containers.
Thanks.
There are two ways to create EntityManager instances.
One way is for SDK applications, and I use this way a lot in unit testing. This is what you have in your example:
EntityManagerFactory factory =
Persistence.createEntityManagerFactory(PERSISTENCE_UNIT_NAME);
In Enterprise applications you let the container create them for you and inject them when needed.
EntityManager is just a wrapper around a JDBC connection. It's very light weight and can be created and destroyed without performance penalty.
Keep in mind that the EntityManager is not thread safe, so if you have one instance, you may need to synchronize access to it. See transaction basics for details.
Here's how I would do it (roughly):
public class BaseDao{
private static final String PERSISTENCE_UNIT_NAME = "Employee";
private static EntityManagerFactory factory =
Persistence.createEntityManagerFactory(PERSISTENCE_UNIT_NAME);
public void create(MyEntiy person){
EntityManager em = factory.createEntityManager();
em.getTransaction().begin();
// do what ever you need
em.getTransaction().commit();
em.close();
}
// add more methods to the dao.
}
Once you get this protoyped and ready, you can use a generic DAO.
Today you should probably look at sometime like spring-data and #PersistanceUnit for managing your EntityManager.
An EntityManager is more than just a wrapper a wrapper for a JDBC connection. It defines the scope of a persistence context, which defines the unit of work that should be performed when a transaction is committed (of when you flush queries to the database). Within a persistence context you are also guaranteed that a given entity in the database will result in the same Java object, regardless if you load it directly, or access it through a OneToMany relation of another entity.
With regards to the original question about obtaining an EntityManagerFactory in a non-spring setting. You simply call
Persistence.createEntityManagerFactory(PERSISTENCE_UNIT_NAME);
This method is a static factory method, depending on your JPA implementation you either get the same instance for the same PU, or a shallow wrapper that wraps the underlying persistence session (of which there is one per PU).

Categories

Resources