I came from the Spring camp , I don't want to use Spring , and am migrating to JavaEE6 ,
But I have problem testing DAO + JPA , here is my simplified sample :
public interface PersonDao
{
public Person get(long id);
}
This is a very basic DAO , because I came from Spring , I believe DAO still has its value , so I decided to add a DAO layer .
public class PersonDaoImpl implements PersonDao , Serializable
{
#PersistenceContext(unitName = "test", type = PersistenceContextType.EXTENDED)
EntityManager entityManager ;
public PersonDaoImpl()
{
}
#Override
public Person get(long id)
{
return entityManager .find(Person.class , id);
}
}
This is a JPA-implemented DAO , I hope the EE container or the test container able to inject the EntityManager (just like Spring does).
public class PersonDaoImplTest extends TestCase
{
#Inject
protected PersonDao personDao;
#Override
protected void setUp() throws Exception
{
//personDao = new PersonDaoImpl();
}
public void testGet()
{
System.out.println("personDao = " + personDao); // NULL !
Person p = personDao.get(1L);
System.out.println("p = " + p);
}
}
This is my test file .
OK , here comes the problem :
Because JUnit doesn't understand #javax.inject.Inject , the PersonDao will not be able to injected , the test will fail.
How do I find a test framework that able to inject the EntityManager to the PersonDaoImpl , and #Inject the PersonDaoImpl to the PersonDao of TestCase ?
I tried unitils.org , but cannot find a sample like this , it just directly inject the EntityManagerFactory to the TestCast , not what I want ...
because I came from Spring, I believe DAO still has its value, so I decided to add a DAO layer.
I don't really see what Spring has to do with this. And I don't agree as I wrote in a previous answer. To me, JPA is a DAL (data access layer), and I don't see the point of putting a data access layer on top of another data access layer. At least not systematically. But let's not discuss this.
This is a JPA-implemented DAO , I hope the EE container or the test container able to inject the EntityManager (just like Spring does).
If your DAO is a managed component like a CDI managed bean, then the Java EE container should be able to inject an EntityManager in it.
For unit testing of container-managed objects, you don't need any kind of container. For integration testing, you will need some kind of container, just like you do for Spring beans, Hibernate/JPA entities, session beans, CDI managed beans or any other kind of container-managed object. You could use the EJB3.1 embeddable API in your tests. Also have a look at Arquillian.
You could also add method PersonDaoImpl.setEntityManager(EntityManager em), then set it by Persistence.createEntityManagerFactory("test").createEntityManager().
It's nothing with Java EE container.
Related
First of all I am new to JPA and Jax-rs, i am trying to develop a rest service. So i have created a resource class and annotated it.
#Path("/companies")
public class CompanyResource {
private EntityManagerFactory entityManagerFactory = Persistence.createEntityManagerFactory("test");
#GET
#Produces({MediaType.APPLICATION_JSON})
public List<Company> getCompanies() {
EntityManager entityManager = entityManagerFactory.createEntityManager();
return new ArrayList<>();
}
#GET
#Path("{companyId}")
#Produces({MediaType.APPLICATION_JSON})
public Company getCompany(#PathParam("companyId") int id) {
return new Company();
}
}
From what i have understood about jax-rs for every client request instance of CompanyResource will be created, that means every time new EntityManagerFactory will be created, which i guess is not a good idea, as i just need it to create entity managers, which could be done with only one instance of it. So what is a proper way to achieve this? Or is it ok to create new instance of this factory for every request?
P.S. i have seen some examples where they use #Stateless annotation and inject Entity Manager, but i guess they use EJB there(i might be wrong) and i don't want to deep into EJB right now.
I think you should inject the entitymanager itself (not the factory), and let the container take care of instantiation and scopes. What we usually do is something like
#Stateless
#Path("services")
public class MyServices {
#PersistenceContext
private EntityManager em;
// ...
apart from the #Stateless (which imho you should use, there's no need to get deep into EJB for this), it's actually quite simple.
Some days ago I heard about spring-boot.
So I started to setup my project from zero, include jpa and dont use older setups from existing projects. But now there is an understanding problem between what I've learned and what I've read about the "easy setup" with spring boot and jpa.
Usually my projects have this structur.
Model (for excample Car)
ModelDao (CarDao with the following code-example)
#Component
public class CarDao {
/** The Hibernate session factory. */
#Autowired
private SessionFactory sessionFactory;
#Transactional
public void save(Car car) {
sessionFactory.getCurrentSession().saveOrUpdate(car);
}
CarServiceImpl thats works with DAO´s (includes methods like findAll(), getCarById() or saveCar(Car car))
But now I only read about #Entity and JPA-repositorys.
Is it right to say that I dont need models and dao's because I have the #Entity-Annotation? And my ServiceImples and JPA-repositorys have the same functionality? What happend with the SessionFactory? Is all managed automatically?
You dont need DAO if you are going to use JPA-Repositories.
As well Session-Factory also not required.
Just you need one Class as model and one interface as repository and you all done.
example:
#Entity
#Table(name="COUNTRY")
public class Country {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
#Column(name="COUNTRY_ID", nullable = false)
private Integer country_id;
#Column(name="COUNTRY_CODE")
private String country_code;
//Add getter and setter
}
interface
public interface CountryRepository extends PagingAndSortingRepository<Country, Integer> {
}
Yes you need to configure in spring.xml about where your above repository is located
<jpa:repositories base-package="com.repository" />
create transactionManager in spring.xml
and access it by using below code
ApplicationContext ctx = new ClassPathXmlApplicationContext(
"spring.xml");
countryRepository = (CountryRepository) ctx.getBean("countryRepository");
Country country = countryRepository.findOne(1);
Is it right to say that I dont need models and dao's because I have the #Entity-Annotation?
#Entity annotation is used on models your POJOs. #Entity maps the POJO i;e class properties to the db table. How would you write your business logic if you get rid of models.
Service layer, DAO layer are all components of application design. They have their specific role. ServiceImpl proverbially manages the transactions whereas DAO/Repository layer manages the communication with the db.
Here your CarDao class should be annotated with #Repository annotation. It is a DAOImpl class.
And all your transactional methods should move to the Service layer.
And my ServiceImples and JPA-repositorys have the same functionality?
No, as I've already stated they have specific respective functionality. They are not same.
What happend with the SessionFactory? Is all managed automatically?
SessionFactory is always injected into the DAO layer. You can either manage the sessions yourself or let hibernate manage the sessions.
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:";
}
}
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.