I have a moderate sized Java EE 6 project that uses several EJBs, including one which sole purpose is managing database calls through JPA. My question is what is the best way to add a new class that does some random bit of functionality and then calls the database access EJB to persist the data from this class.
Does this new class have to be an EJB if it needs access to annotations and injections? Does it have to be an EJB if it has to be deployed with the rest of the project?
I was told that if you want to add a new logic class to the project it either has to be an EJB or you can remotely integrate it using JNDI to access EJB elements and create some kind of client interface. Right now my new class is just a POJO but it's not able to access the EJB functionality.
What should I do in general?
EDIT: Please note my question IS NOT about database access. That's just an example I'm using. My guestion is more broad. I want to know how to access EJB methods from other classes I create. From one EJB to another you can simply inject the other EJB since they're both container managed. But say I create another class in the same package as the EJBs how might How can I access those methods? Is it possbile? What is the best practices here.
Right now I have a class that is taking twitter feed data from a URL it then parses the JSON and returns a string of the top 10 entries. I want to call my EJB that manages database access and pass that string to its corresponding method but I cannot do that because my class is not also an EJB.
EJBs are generally used to implement services of any kind. They integrate really well with JPA so are often used for DB access, but that's not their only usage.
What EJBs are typically not suited for is modeling data. I.e. they should be the verbs in your application, not the nouns. The following is thus wrong:
#Stateless
#Entity
public class CreditCard { // silly, don't do this!
#Id
Long id; + getters/setters
Data expiration date; + getters/setters
}
The following is better, it's a service that when your application starts up fetches some quote data from somewhere:
#Singleton
#Startup
public class QuoteFetcher {
private List<Quote> quotes; // + getter
#PostConstruct
public fetchQuote()
quotes = SomeUrlBuilder.someUrl().getQuotes();
}
}
The following is the obligatory DAO example:
#Stateless
public class JPAInvoiceDAO implements InvoiceDAO {
#PersistenceContext
private EntityManager entityManager;
public Invoice getById(Long invoiceId) {
return entityManager.find(invoiceId, Invoice.class);
}
// More DAO methods
}
The following shows how declarative security is used, and how a bean looks up something that has been externally mapped into its private context (ENC):
#Stateless
public class TokenFetcher
#Resource
private SessionContext sessionContext;
#RolesAllowed("SYSTEM")
public Token getToken() {
return (Token) sessionContext.lookup("token");
}
}
The second part of the question seems to be how to use these beans in your code. There are basically four methods:
Injection in managed beans
Bootstrapping via JNDI
Automatically called at startup
Automatically via a timer
Injection is the easiest way, but only managed beans are injection candidates (basically meaning the Java EE framework creates the bean, and you don't use new() to instantiate it).
E.g. Injection:
#ManagedBean
public class InvoiceBacking {
private Long invoiceId; // + getter/setter
private Invoice invoice; // + getter
#EJB
private InvoiceDAO invoiceDAO;
#PostConstruct
public void init() {
invoice = invoiceDAO.getById(invoiceId);
}
}
(also see Communication in JSF 2.0#Processing GET request parameters)
Bootstrapping via JNDI:
public class SomeQuartzJob implements Job {
public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException {
InvoiceDAO invoiceDAO = (InvoiceDAO) new InitialContext().lookup("java:global/myApp/myEJB/InvoiceDAO");
List<Invoice> openInvoices = invoiceDAO.getAllByOpenStatus();
// verbose exception handling and closing JNDI context omitted for brevity
}
}
The #Singleton bean showed earlier was an example of how the Java EE framework calls your code itself at startup. For the automatic timer you would use the #Schedule annotation on a bean's method.
Related
I have this scenario where i have my EJB3 beans in a jar file, deployed successfully to Jboss EAP-6.4.
Then I have another web project that looks up these EJB's inside a REST POJO class. I can currently access the EJB's from inside the web project using #Inject and #EJB, but my use case is one that i don't know which beans i need to load until runtime and the list is not static, so i might need to lookup 10 EJB's or none for a particular request etc.
I know I can possibly use
InitialContext.lookup('ejb:/.....')
to retrieve my EJB beans from inside the web project, but is there a way that i can retrieve them without that round trip(i believe), or maybe what am just looking for is a more elegant way to do EJB look-up at runtime just like the statically typed #EJB and #Inject versions.
Any suggestions are greatly appreciated.
EDIT
In my REST POJO classes i don't want to hard code any #Inject or #EJB annotations, rather i want that when a request comes in i look-up(for lack of better word) the EJB's that will handle the request, so all the decision is made at runtime really, as shown below
#Path("/path")
public class TestService {
#GET("/{id}")
public String loadGetPath(#Param id int id){
//at this point i want to dynamically resolve the EJB based on
//the value of id
}
}
Whoopdicity blog: Developing a dynamic JEE service client with CDI seems to have what you are looking for. At the end it claims you can do:
public class MyServiceConsumer {
#Inject #ServiceClient
private MyBusinessService service;
...
}
Instead of
public class MyServiceConsumer {
#EJB(lookup="...")
private MyBusinessService service;
...
}
Let's suppose I have a simple lib named db-utils, which has a CrudService CDI bean (requestScoped) that's used by my web applications to perform CRUD operations.
I also have an EJB project named grad-db, which has the entities mapped from database. Grad-db also has the producer used to set the entityManager in db-utils' CrudService.
I already tried it and apparently it works fine. My question is: is that a bad practice? Is there any consequence of producing a CDI bean inside a stateless session bean and passing the EJB stateless bean as a parameter to the CrudService?
My code:
EJB Bean (grad-db):
#Stateless
public class CrudServiceCae extends AbstractCrud implements Serializable {
private static final long serialVersionUID = 1L;
#PersistenceContext(unitName = "cae-pu")
EntityManager em;
#Override
public EntityManager getEntityManager() {
return em;
}
#Produces
#Database(Schema.CAE)
public CrudService createCrudServiceCou() {
return new CrudService(this);
}
}
CrudService (db-utils):
#Named("crudService")
public class CrudService implements Serializable {
private static final long serialVersionUID = -2607003150201349553L;
private AbstractCrud crud;
public CrudService(AbstractCrud abstractCrud) {
this.crud = abstractCrud;
}
...
}
Edit:
Actually it worked only for queries. When I tried to insert data I got javax.persistence.TransactionRequiredException. Apparently I'm going to have to use inheritance instead of CDI in this case.
The EJBs are responsable for business processes/logic (i.e: methods), and are able to orchestrating others CDI controllers, is not so common let the EJB create objects, for that you would prefer a CDI POJO Producer.
In your case is leaner to use a CDI object and produce the object that you need from there, looks like a DAO and could be used (i mean, injected) into the EJB.
Think of EJBs on terms of a Boundary Pattern, using specialized controllers.
Notes:
#Stateless is not required to implements Serializable, these are pooled, and its lifecycle does not allow serialization.
In general you dont want to use a getter to the entity manager of an EJB, you should prefer write a method and use the em internally.
The persistence context is easier to manipulate if uses JTA
Your #Stateless should begins the transactions and let them propagated along the controllers
The em with package visibility is a good idea, lets you mock your facade / boundary easily
I'm trying to figure out how to setup a Service/Dao layer in my application. I've found a few dozen resources all with different ways on how to do it and decided to follow the model found here: How should EntityManager be used in a nicely decoupled service layer and data access layer?
I can't figure out what I'm missing that's causing this NPE.
Usage:
#Path("/helloworld")
public class MyController {
#GET
#Produces(MediaType.TEXT_PLAIN)
public String TestRequest() {
Workflow workflow = new Workflow();
workflow.setName("test");
WorkflowService workflowService = new WorkflowService();
workflowService.save(workflow);
return "Workflow ID:";
}
}
My Dao:
#Stateless
public class WorkflowDao {
#PersistenceContext(unitName = "unit")
private EntityManager entityManager;
public int save(Workflow workflow) {
entityManager.persist(workflow);
return workflow.getId();
}
}
My Service:
#Stateless
public class WorkflowService {
#EJB
WorkflowDao workflowDao;
public int save(Workflow workflow) {
int id = workflowDao.save(workflow); //throws NullPointerException because workflowDao is null
return id;
}
}
This is my first time setting up a Java project (only have worked on 1 before and it used Spring) so please keep that in mind if this looks horribly wrong.
WorkflowDao is not an EJB, it's a POJO with a#Stateless annotation. So naturally, injecting it with #EJB fails, creating a null workflowDao attribute and eventually producing a NullPointerException.
To make WorkflowDao into a full-fledged EJB, besides having a #Stateless or #Stateful annotation it needs to implement a local, remote or both interfaces, and those interfaces must be annotated respectively with #Local and #Remote. Please refer to the tutorial for details.
Also, quite possibly (this can be application server-dependent) you'll have to register the EJB in the application's xml descriptor files - for instance, in web.xml's <ejb-local-ref> element.
As a side note - it's not a good idea to use an EJB as a DAO, an EJB is typically used for implementing business logic (true, persist/merge operations can be called from here) but the actual persistence layer nowadays is implemented using JPA. In other words, WorkflowService should be the EJB service, there's no need to inject an EJB into it, and there's no need for a separate DAO layer - JPA entities fulfill this role.
If you instantiate your WorkflowService manually, the container wont perform any injection, since your WorkflowService is not managed by the Container.
I suggest you:
Annotate your Jax-RS Resource #Stateless
Inject your WorkfloService via #EJB as a member
Implementing a Local or Remote Interface is not necessary anymore
#Path("workflows")
#Stateless
public class WorkFlowResource{
#EJB
WorkflowService workflowService;
#GET
#Produces(MediaType.TEXT_PLAIN)
public String TestRequest() {
Workflow workflow = new Workflow();
workflow.setName("test");
workflowService.save(workflow);
return "Workflow ID:";
}
}
im programming a project and im trying to apply multitier architecture.
Right now ive got 2 EJB, business and persistence and a shared jar. Due a funcional requirment, persistence must be replaceable. I made an Interface called IPersistence.
Then I crated a remote session bean called "persistence" inside the persistence EJB and put the remote interface in the shared library. Now, i need to call an IPersitence using injection from the business. How can i do that? Maybe the whole idea is wrong. I need some advice.
Thanks!
Here is a simple example where you have a car repository/DAO that abstracts the persistence from the business logic by not exposing if it is stored in a database, file, XML etc. The business class then injects an instance to be able to - in this case - save to an database. However you could have made other classes that implemented the CarRepository and provide other means for saving data in your application without touching other parts of your code.
Persistence layer
Interface for the repository/DAO
#Local
public interface CarRepository {
List<Car> findAllCars();
// Many other methods
}
Repository (Domain driven design) or Data Access Object
#Stateless
public class CarSqlRepository implements CarRepository {
#PersistenceContext(unitName = "MyUnit")
private EntityManager entityManager;
public List<Car> findAllCars() {
}
// Many other methods
}
Service/business layer
#Stateless
public class CarService {
#Inject
private CarRepository carRepository;
public List<Car> findAllCars() {
return carRepository.findAllCars();
}
// Many other methods
}
I have a POJO class with a method annotated with #Transactional
public class Pojo {
#Transactional
public void doInTransaction() {
...
}
}
Spring declarative transaction management is based on AOP but I don't have any experience with that. My question is:
Is it possible that when invoking the (new Pojo).doInTransaction() alone, Spring will start a Transaction.
Spring declarative transaction
management is based on APO but I don't
have any experience with that.
I would recommend to start working with it and you will get the experience of using transaction advices using AOP. A good starting point is here.
Is it possible that when invoking the
(new Pojo).doInTransaction() alone,
Spring will start a Transaction.
No, you can't expect Spring to be aware of a bean that you manually invoked. However, it sounds like that you are wanting to avoid declarative transaction management and do programmatic transaction management. There is a way to do that with Spring using the Transaction Template. Is that what you were looking for?
It is somewhat possible, but in a cumbersome way: You must use the AutowireCapableBeanFactory mechanism.
Here is a transactional class as example
public interface FooBar{
void fooIze(Object foo);
}
public class FooBarImpl implements FooBar{
#Transactional
#Override
public void fooIze(final Object foo){
// do stuff here
}
}
And here is how we can use it:
public class FooService implements ApplicationContextAware{
private ApplicationContext applicationContext;
#Override
public void setApplicationContext(
final ApplicationContext applicationContext){
this.applicationContext = applicationContext;
}
public void serviceMethod(){
//declare variable as interface, initialize to implementation
FooBar fooBar = new FooBarImpl();
// try to use it, won't work, as it's not a proxy yet
Object target = new Object[0];
fooBar.fooIze(target); // no transaction
// now let spring create the proxy and re-assign the variable
// to the proxy:
fooBar = // this is no longer an instance of FooBarImpl!!!
(FooBar) applicationContext
.getAutowireCapableBeanFactory()
.applyBeanPostProcessorsAfterInitialization(fooBar,
"someBeanName");
fooBar.fooIze(fooBar); // this time it should work
}
}
This is not a best practice. For one thing, it makes your application highly aware of the Spring Framework and also, it violates the dependency injection principles. So use this only if there is no other way!
Yes, it is possible. Spring does not require the use of dynamic proxies for #Transactional to work. Instead, you can use "true AOP", as provided by AspectJ.
For the details, see http://static.springsource.org/spring/docs/3.0.x/spring-framework-reference/html/transaction.html#transaction-declarative-aspectj
The way Spring handle the transaction through Annotation is using AOP as you've said.
The AOP bit is implemented using Dynamic Proxies (see doc)
So in order to do so you'll need to retrieve an instance of your class (Pojo here) through the spring container since to make it work, Spring will return you a Dynamic Proxy over your Pojo that will automatically surround any annotated method with the transaction management code.
If you simply do a
Pojo p = new Pojo();
p.doInTransaction();
Spring doesn't have any role to play here and your method call won't be inside a transaction.
so what you need to do is something like this
ApplicationContext springContext = ...;
Pojo p = (Pojo) springContext.getBean("your.pojo.id");
p.doInTransaction();
Note: this is an example, you should prefer dependency injection instead of retrieving your bean manually from the context
By doing so, and with a properly configured Spring Context, Spring should have lookout your classes to scan for transactional annotation and automatically wrapped your beans into annotation aware dynamic proxies instances. From your point of view that doesn't change anything, you'll still cast your object to your own Classes, but if you try to print out the class name of your spring context Pojo bean, you'll get something as Proxy$... and not your original class name.
Have a look at this link anyway : link text