Persisting my first entity using Java EE - java

Trying to get my head around Java EE (ORM/Entities/Annotations/EJB/Servlets etc.). So I've created a very simple webpage where you can enter user information and send it to the server. I'm using Apache Tomcat 8.0 as webbserver application and here is all the relevant parts of the application files and content that is needed to persist an entity:
http://pastebin.com/fwfbnYpU
The application gives me the error on line 99 saying:
08-Apr-2014 16:18:10.329 SEVERE [http-nio-8084-exec-93] org.apache.catalina.core.StandardWrapperValve.invoke Servlet.service() for servlet [indexServlet] in context with path [/JavaEENackademin] threw exception
java.lang.NullPointerException
What am I doing wrong? The database exist with the correct named table and columnnames. But then again that is not the problem here maybe it will become a problem after I fix this problem :)

One issue with your code is that you should not inject EntityManagers into servlets. Servlets are usually singletons, so all servlets would use the same EntityManager. You should inject an EntityManagerFactory instead and get your EntityManagers from it. You also have to take care of transactions. Not sure if this has caused your issues, but something that should be fixed.

I'm surprised you are able to deploy the code in your pastebin. Especially:
#WebServlet(name = "indexServlet", urlPatterns = {"/indexServlet"})
public class indexServlet extends HttpServlet {
#Inject
LoginValidation validation;
#PersistenceContext(unitName = "JavaEENackademinPU")
private EntityManager em;
//... offending line 99 calls: em.persist()
}
Neither PersistenceContext nor Inject are part of the servlet spec, so you probably added additional jars to your installation.
But you configured your persistence.xml to use JTA transactions which are barely supported in a servlet environment, probably resulting in tomcat ignoring the #PersistenceContext annotation altogether and leaving em == null (the default value).
I've found this link describing an integration but it looks complicated, requires editing internal xml files and then goes on to use Spring. Likely every part of that is overkill for a beginner.
I suggest you start fresh with a copy of TomEE which already does all the wiring to get you a fully fledged application server that supports CDI (#Inject) and JPA (#PersistenceContext) out of the box.

Related

Why Spring does not recognize #BatchSize annotation

Scenario:
I'm supporting an Enterprise application that runs in Wildfly10. The application (.war) uses J2EE technologies (EJBs, JPA, JAX-RS) and SpringBoot features (like, SpringMVC, SpringRest, SpringData, SpringRestData) ... Both stacks co-exists "happily" because they don't interact between them; however, they do share common classes, like utility or Entity Classes (the stacks map to the same database model). Why the application uses those stacks is out the scope of the question.
Currently, I'm trying to improve the performance of a #RestController that pulls some data from the database using a JPA Spring Repository. I found that we're suffering the N + 1 queries problem when calling the #RestController. In past projects (where there were only J2EE technologies), I have used the #BatchSize hibernate annotation to mitigate this problem with total success.
But, in this project, Spring seems to be skipping such annotation. How do I know that? Because I turned on the hibernate SQL logging (hibernate.show_sql) and I can see the N + 1 queries is still happening ...
Key Points:
Here are some insights about the application that you must know before providing (or trying to guess) any answer:
The application has many sub-modules encapsulated as libraries inside WAR file (/WEB-INF/lib) ... Some of these libraries are the jars that encapsulate the entity classes; others are the jars that encapsulate the REST Services (that could be JAX-RS services or Spring Controllers).
The Spring configuration is done in the classes defined in the WAR artifact: in there, we have a class (that extends from SpringBootServletInitializer) annotated with #SpringBootApplication and another class (that extends from RepositoryRestConfigurerAdapter) annotated with #Configuration. Spring customization is done is such class.
The application works with multiple datasources, which are defined in the Wildly server. Spring DATA JPA must address any query pointing to the right datasource. To accomplish this requirement, the application (Spring) was configured like this:
#Bean(destroyMethod="")
#ConfigurationProperties(prefix="app.datasource")
public DataSource dataSource() {
// the following class extends from AbstractRoutingDataSource
// and resolve datasources using JNDI names (the wildfly mode!)
return new DataSourceRouter();
}
#Bean("entityManagerFactory")
public LocalContainerEntityManagerFactoryBean getEntityManagerFactoryBean() {
LocalContainerEntityManagerFactoryBean lemfb;
lemfb = new LocalContainerEntityManagerFactoryBean();
lemfb.setPersistenceUnitName("abcd-pu");
lemfb.setDataSource(dataSource());
return lemfb;
}
The last #Bean declaration favors the use of a persistence.xml file, which we do have in the route /WEB-INF/classes/META-INF/ (i.e. Spring does find this file!) ... In such file, we define our domain classes, so that Spring JPA can see such entities. Also, we can define special JPA properties like: hibernate.show_sql and hibernate.use_sql_comments without issues (this is how I detected the N + 1 queries problem in the first place) ...
What I have done so far?
I tried to add the #BatchSize annotation to the problematic collection. No luck!
I created a new JAX-RS Service whose purpose was to mimic the behavior of the #RestController. I confirmed that the #BatchSize annotation does work in the application's deployment, at least, in JAX-RS Services! (NOTE: the service uses it own persistence.xml) ...
Test details (Updated 2020/07/30): What I did here was to create a new JAX-RS Service and deployed it inside the WAR application, next to the #RestController that presents the problem (I mean, it is the same WAR and the same physical JVM). Both services pull from database the same entity (same class - same classloader), which has a lazy Collection annotated with #BatchSize! ... If I invoke both services, the JAX-RS honors the #BatchSize and pulls the collection using the expected strategy, the #RestController does not ... So, what it is happening here? The only thing different between the services is that each one has a different persistence.xml: the persistence.xml for the JAX-RS is picked by Wildfly directly, the other one is picked by Spring and delegated to Wildfly (I guess) ...
I tried to add the properties: hibernate.batch_fetch_style (=dynamic) and hibernate.default_batch_fetch_size (=10), to the persistence.xml read by Spring ... No luck. I debug the Spring startup process and I saw that such properties are passed to the Spring Engine, but Spring does not care about them. The weird thing here is that properties like: hibernate.show_sql, Spring does honor them ... For those who are asking: "What does these properties do?" Well, they are global equivalent to apply #BatchSize to any JPA lazy collection or proxy without declaring such annotation in any entity.
I setup a small SpringBoot Project using the same Spring version as enterprise application (which is 1.5.8.RELEASE, by the way) and both the annotation and properties approach worked as supposed to.
I've been stuck with this issue for two days, any help to fix this will be appreciated ... thanks!
There are 2-3 possible issues that I can think off.
For some reason, whatever you modify isnt picked up by wildfly - Wildfly classpath resolution is a separate Topic and some missing configuration can cause you a nightmare. This you can identify if you have access to debug the query, and in if you put a breakpoint in the constructor of your Entity class, you will get a chance to evaluate the entity configuration being used, somewhere in the execution conetxt.
BatchSize doesnt work on OneToOne, It only works on OneToMany relationships.
A typical way to define BatchSize is to do along with Lazy load as mentioned in the example here. If you are not using Lazy fetch, hibernate assumes that you are willing to make an eager load and makes another select query to fetch all the details.Please confirm you are using the same syntax as given in the example above.
New Addition:
Put Conditional Breakpoints in PropertyBinder#setLazy() function, and may be backtrace it and put relavent breakpoints in CollectionBinder and AnnotationBinder. then restart/redeploy the server and see what data you are getting for the relavent properties. That will give you fair idea where it is failing..
Why conditional breakpoint? Its because you will have thousands of properties and if you do not add condition to the breakpoint, you will take 1 hour to reach your actual breakpoint
What should be the condition - If its property binder, the condition shoud be like `this.name == . For other classes also you can use the same approach.
Sorry for too detailed description on conditional breakpoints, you might find it redundent.
Looks like the only way to debug your problem is to debug hibernate framework from server startup, then only we will be able to find out the rootcause

Spring, Interceptors, some ExtJs and a HibernateException on console vs IntelliJ

Weired world... let me try:
I have the follwing mavenized setup:
- Springboot (1.5.5.RELEASE)
- Hibernate (5.0.9.Final; I do know there is newer variants but I stick with what I have right now)
- ExtJs (6.0.0)
- IntelliJ (2017.3)
I do partly get running into an Hibernate Exception:
2018-11-20_15:04:58.007 [http-nio-8081-exec-7] [ERROR] o.a.c.c.C.[.[.[/].[dispatcherServlet]:181 - Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is org.hibernate.HibernateException:
Could not obtain transaction-synchronized Session for current thread] with root cause
org.hibernate.HibernateException: Could not obtain transaction-synchronized Session for current thread
at org.springframework.orm.hibernate5.SpringSessionContext.currentSession(SpringSessionContext.java:133)
at org.hibernate.internal.SessionFactoryImpl.getCurrentSession(SessionFactoryImpl.java:697)
...
This does not happen on all threads! Partly the requests from ExtJs go through, Partly they don't. But would they not open a transaction on the webserver side?
I do have an Interceptor; well a web Interceptor implementing org.springframework.web.servlet.HandlerInterceptor
Within the interceptor's preHandle method I do call a Service in order to check if a user is logged in and do some rights management handling.
The called #Autowired service fails. I thought the fact of accessing an #Autowired service method takes care of session/transaction handling.
Well, this was the scenario having my project manually created and run with a java-8 (java 8 sdk; not 9, not 10, not 11) command like from the console:
mvn clean package -DskipTests && java -jar target/MyBuild.jar application-local.properties
I just observed that the login consists of three request from browser to the backend. These three are all handled in separate threads by the backend.
When running the project within IntelliJ it all works fine. Ok, IntelliJ most likely does not jar the application and builds its own startup command.
But exactly that brings me out of rhythm due to the fact that we do process the code through a deployment / CI pipeline where we manually build the project.
And that is where it fails :-(
Amendment:
I changed everything to run with JPA instead of Hibernate (well it is still hibernate in the background). Just as 'M. Deinum' suggested.
Now, the problem still exists.
Two things I somewhat extracted.
In my Interceptor I do have some logging calls which ask the EntityManager for a hibernate-session (entityManager.unwrap( Session.class )).
This is the point where now.
So it seems that on the preHandle(...) of my interceptor there is sometimes no current session active. I am stating 'sometimes' since there are calls to the Interceptor when it works.
The exception comes as following now:
java.lang.IllegalStateException: No transactional EntityManager available
at org.springframework.orm.jpa.SharedEntityManagerCreator$SharedEntityManagerInvocationHandler.invoke(SharedEntityManagerCreator.java:272)
at com.sun.proxy.$Proxy117.unwrap(Unknown Source)
at com.mypackage.dataaccess.DataAccessImpl.getCurrentSession(DataAccessImpl.java:89)
at com.mypackage.dataaccess.DataAccessImpl.queryByHQL(DataAccessImpl.java:382)
Ok. I ended up noting all Spring web controllers to have an #Transactional (where DB usage is given.)
That works.
From my understanding it does not matter where to put the #Transactional annotation as long as the method/owning Object is invoked through spring's #Autowire mechanism.
If I want something to run under the transactional behaviour I would annotated with it on the closest scope possible.
That's how I would decide where to put the #Transactional
At the end it does work but I am not satisfied with the solution.
If anyone could clarify the behaviour and/or my understanding let me welcomely know :-)

Glassfish 4 scans for #PostConstruct with CDI disabled

I'm doing and upgrade from Glassfish 3.1.2.2 to Glassfish 4.1 for a set of Spring applications. Since I use the Spring to handle #Inject annotations, I have disabled Glassfish' CDI using this command:
asadmin set configs.config.server-config.cdi-service.enable-implicit-cdi=false
Still, when I deploy one of my applications, I get the following error message:
The lifecycle method [something] must not throw a checked exception.
Related annotation information: annotation [#javax.annotation.PostConstruct()]
on annotated element [public void com.something.MyClass.something() throws
java.io.IOException] of type [METHOD]. Please see server.log for more details.
The class in question is an abstract class with no implementations in the application that I'm trying to deploy, it's just something that is on my classpath.
Why is Glassfish validating my #PostConstruct when I've disabled CDI? Why is Glassfish validating #PostConstruct on something that can not become a bean?
How can I prevent Glassfish from interferring with anything that I'm using Spring for?
Annotation #PostConstruct is a general annotation used in any dependency injection mechanism. The Javadoc explicitely states that, unless used within an interceptor, it must be put on a method, which has void return type and throws no checked exceptions.
It is weird that Spring allows checked exceptions on post-construct methods, as there is not way how to handle them. But as this requirement is only a validation and can be ignored, Spring probably ignores checked exceptions and Glassfish does not. There is possibly an unnecessary Glassfish feature, that it scans and validates all classes, even if not used in CDI or any other mechanism (EJB, ...)
The best is to remove checked exceptions to align the code with the documentation and make it portable.
You can solve this issue first by adding a web.xml with metadata-complete="true". Next you will want to make sure your context are in the Web root Directory /WEB-INF/.
With this glassfish can load all #PostConstructSpring dependencies.
More of a work around in my opinion.

Creating EJB 3.0 or 3.1

I would be very much thankful to clear me some question about this new EJB3.0 and above version:
1) if suppose I need ejbCreate, ejbActivate and all other events so how can I get it from the new EJB3.0 and above ver.
2) I always have problem to find particular xml file to alocate a JNDI name according to variety of Application Servers so is there any way that I can give JNDI name without xml file and can also be use a portable name that in every Application Server it can be findable of EJB deployed on app server remotely
3)Can any buddy tell me, i have hosting plan of Java/Linux which supports
i) Tomcat - 5.5.xSupport
ii)JDK - 1.6.x Support
iii)JSP/servlet - 2.0 Support
can it be possible that EJB 3.1 be deployed because some where i have got that tomcat is not able to deploy EJB so please give me some advice help...
Thank You...!!!
please Help me...!!!
1) if suppose i need ejbCreate, ejbActivate and all other events so
how can i get it from the new EJB3.0 and above ver.
In EJB 3 and above, the EJB lifecycle is handled through life cycle annotations, such as: #PostConstruct and #PreDestroy.
2) i always have problem to find perticular xml file to alocate a JNDI
name according to variety of Application Servers so is there any way
that i can give JNDI name without xml file and can also be use a
portable name that in every Application Server it can be findable of
EJB deployed on app server remotly
The #Stateless and #Stateful annotations have two attributes that might solve this issue (name and mappedName). Yet
The mapped name is product-dependent and often installation-dependent.
Hope it helps you.
1) ejbCreate, ejbActivate etc. are related to EJB 2.x, if you need similar functionality in EJB 3.x, you should decorate your methods with annotations #PostActivate, #PrePassivate etc. Method signature should follow certain rules, example for #PostActivate:
The method annotated with #PostActivate must follow these
requirements:
The return type of the method must be void.
The method must not throw a checked exception.
The method may be public, protected, package private or private.
The method must not be static.
The method must not be final.
This annotation does not have any attributes.
2) It seems that you're referring to name and mappedName attributes of #Stateless and #Stateful annotations. For more details see official documentation. From my experience mappedName is better, but it's application-server-specific, e.g. on Glassfish it works perfectly. Example:
#Stateless(mappedName="ejb/myBean")
public class MyFirstBean {
..
}
Since no one answered Question 3 ..
3)Can any buddy tell me, i have hosting plan of Java/Linux which supports i) Tomcat - > 5.5.xSupport ii)JDK - 1.6.x Support iii)JSP/servlet - 2.0 Support
No, you are going to need a server that supports Java EE. Read How to deploy EJB based application on Tomcat

Annotations (#EJB, #Resource, ...) within a RESTful Service

I'm trying to inject a EJB within my RESTful Service (RESTEasy) via Annotations.
public class MyServelet implements MyServeletInterface {
...
#EJB
MyBean mybean;
...
}
Unfortunately there is no compilation or AS error, the variable "mybean" is just null and I get a NullPointerException when I try to use it.
What I'm doing wrong?
Here are some side-informations about my architecture:
JBoss 4.2.2.GA
Java version: 1.5.0_17
local MDB-Project
remote EJB-Project
WAR Project with the RESTful Service which uses the remote EJB and sends messages to the local MDB-Project
Thanks in advance!
br
Dominik
p.s: everything is working fine when I use normal context lookup.
I had a similar problem (though without #Remote beans). The way it worked for me - sample application is here: https://github.com/kubamarchwicki/rest-app/ (this works: https://github.com/kubamarchwicki/rest-app/blob/master/service-webapp/src/main/webapp/WEB-INF/web.xml#L9)
The crack with context lookup is that the name changes with a change of the ear name. If you fancy things like versions, it makes the whole thing hard to trace or forces you to hardcode ear name somewhere in the code.
Just a few cents to an old discussion ;-)
This is not exactly my forte, so maybe I am way off... but, can you do EJB stuff in a WAR? I was under the impression you needed to do EJB work in an EAR.
JBoss 4.2.2.GA is not a fully compliant Java EE 5 server, it does not support EJB references injection in servlets or application clients, only in the EJB layer. Use JBoss 5 for that (or perform a lookup).
JBoss 4.2.2.GA supports only Servlet 2.4. There is no support of DI on Servlet 2.4. Hence you always get 'null' for myBean variable. As suggested, please migrate to JBoss 5.0 which supports Servlet 2.5 which makes use of Java 5 features like annotations.

Categories