I'm very new to Spring, but I am working on a project which is using Spring Data JPA to generate repositories for JPA entities.
I'm currently adding a simple module to be able to show some data on a webpage. I have added a Servlet, but I am having trouble accessing the repositories from there.
I have added a ContextLoaderListener in web.xml, I'm referencing the jpa:repositories and persistence.xml in the applicationContext.xml, but I'm currently stuck with this exception:
No unique bean of type [javax.persistence.EntityManagerFactory] is defined: expected single bean but found 0.
But when I add an EntityManagerFactory in persistence.xml I get the following cryptic message:
java.lang.IllegalAccessError: tried to access field
org.hibernate.engine.spi.CascadeStyle.STYLES from class
org.hibernate.engine.spi.EJB3CascadeStyle
My question is: is what I am trying to do even possible? And if so, how?
Or should I just bite the bullet and use Spring MVC or something else entirely?
Note: this is just for a one-page web site and I'm trying to keep it as simple as possible.
In order to use Spring Data JPA you need to configure the underlying JPA implementation as you would typically do in Spring, see for example, infrastructure.xml and META-INF/persistence.xml in spring-data-jpa-showcase (since Spring 3.1 you can get rid of persistence.xml if you use packagesToScan property of LocalContainerEntityManagerFactoryBean).
Your second problem with IllegalAccessError looks like a classloading problem caused by presence of different versions of Hibernate jars in classpath.
Related
I need to fetch a property with the following format:
${/a/env/mode}
However this depends on where im deployed, I have all the required information in configuration already and is trying to use the following:
${/a/${env}/${mode}}
This is not working as expected in Spring Boot but instead gives an exception. Is there anyway to get what I need?
I am attempting to convert an existing spring weblogic application to a spring boot embedded tomcat application.
There are lots of moving parts so it's hard to show any code, I'm hoping there is some general answer that might clue me in to the issue.
Under weblogic, using the spring-framework 4.3.6.RELEASE libraries, the application deploys fine. It has no problems creating the different service, repository and component beans.
However, when I migrate it to Spring Boot 1.5.1.RELEASE, I get the following error:
2017-06-21 17:08:16,402 [ERROR] SpringApplication reportFailure (815) - Application startup failed
org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'alertEventServiceImpl': Unsatisfied dependency expressed through field 'alertEventDao'; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'alertEventDaoImpl' defined in URL [jar:file:/Users/username/Development/source/carma-war/target/carma-war-2.0.0-SNAPSHOT.war!/WEB-INF/lib/protocol-manager-1.8.0-SNAPSHOT.jar!/org/ihc/hwcir/protocol/dao/AlertEventDaoImpl.class]: Initialization of bean failed; nested exception is org.springframework.aop.framework.AopConfigException: Could not generate CGLIB subclass of class [class org.ihc.hwcir.protocol.dao.AlertEventDaoImpl]: Common causes of this problem include using a final class or a non-visible class; nested exception is java.lang.IllegalArgumentException: Cannot subclass final class org.ihc.hwcir.protocol.dao.AlertEventDaoImpl
Many of our service classes are final as they shouldn't be extended. Since there are so many that are final, I wanted to minimize the amount of code in our different libraries that we modify to make this work.
I thought because the bean creation process works under weblogic, it should work under spring boot.
Things I have tried to force not using the cglib proxies:
All implementations implement interfaces already
In beans created via xml, added <aop:scoped-proxy proxy-target-class="false"/>
In beans created through annotations, added (example for service bean)
#Service
#Scope(proxyMode = ScopedProxyMode.INTERFACE)
However, in the end, I'm perplexed as to why spring can create beans (the classes marked as final) under the weblogic container but unable to do so under the embedded tomcat spring-boot container.
Spring Boot by default uses class based proxies, which will not work with final classes/methods.
To disable this add spring.aop.proxy-target-class=false to the application.properties to enable JDK Dynamic Proxies instead of class based proxies. (And revert your modifications).
NOTE: To have everything take into account the spring.aop.proxy-target-class you might need to upgrade to Spring Boot 1.5.3 as some final patches where made to include this property in parts that were missed in previous versions.
See the following issues for more information 8434, 8869 and 8887.
I was unable to make this work using M. Deinums' answer using spring.aop.proxy-target-class=false.
What worked for me was to add in the application.properties file
spring.dao.exceptiontranslation.enabled=false
Please note that this option disables proxy creation for repositories.
And in my spring boot application configurer the annotation to handle transactions without using a proxy class.
#EnableTransactionManagement(proxyTargetClass = false)
This is using Spring Boot version 1.5.1.RELEASE.
I am trying to figure out how can I dynamically update/reload externalized configuration in a Spring Boot application without restarting the whole application.
Most of the advice involves reloading ApplicationContext after changing the externalized configuration, but that is equivalent to restarting the entire application, so this is not really all that useful.
Reading through SpringBoot reference documentation, I found a chapter 23.7 Typesafe Configuration Properties.
If I understand it correctly, this allows to define simple POJO classes that will hold your application (externalized) configuration values as attributes.
In theory at least, this scheme could be used to bind beans only once to the required configuration POJO and upon configuration change just update the values in the POJO. Components could easily pick up the changes next time they access getters on the POJO...
However, I have yet not managed to figure out how to enable this type of behavior. Is there some glaringly obvious way to dynamically update components annotated with #ConfigurationProperties when relevant configuration has changed?
It sounds like you're looking for #RefreshScope which is provided by Spring Cloud. From the Spring Cloud documentation:
A Spring #Bean that is marked as #RefreshScope will get special treatment when there is a configuration change. This addresses the problem of stateful beans that only get their configuration injected when they are initialized. For instance if a DataSource has open connections when the database URL is changed via the Environment, we probably want the holders of those connections to be able to complete what they are doing. Then the next time someone borrows a connection from the pool he gets one with the new URL.
I am new to Spring and the bean concept, so sorry if asking the obviously.
I have set up a Java project and used the Hibernate framework to make my connections to the DB (using hibernate tool on eclipse, really recommended btw).
My basic setup was as follows:
some hibernate pojos (generated by Hibernate tools),
hibernate mapping files (hbm.xml files).
The configuration was set in hibernate.cfg.xml file placed at my root of the packages.
I initially setup a HibernateUtils class that gets a session from my sessionFactory.
some classes that act as Dao - creates the queries using the pojos and the hibernateUtils to get the session.
This was working fine with hibernate's powerful framework. Then I migrated to project to Spring MVC. From the various tutorials I read I understood that some changes need to be done in order to make things play nicely again. The main change is that the Spring FW now loads the beans by itself, therefore the following:
the pojos did not change, nor did the hbm.xml files
The configuration is no longer set at hibernate.cfg.xml - the Spring MVC FW loads it's own LocalSessionFactoryBean once I declared it in the XML files (Spring search for xmls as part of the initialization process). So I created a separate xml file called spring-hibernate.xml, that has the DB definition, the session factory bean and a hibernate template. To complete it, the xml file also declare the location of the Dao and the hbm files.
with hibernate template configured in the xml, there is a bean injection, therefore I changed the Dao files to add getter/setter to a hibernate template property. Then using this - the Dao class may create the db query.
All of this configuration works fine and I can get the Spring FW initialize the Dao classes (I put a sysout just to confirm that the Dao classes are injected with the hibernate template during MVC startup). Now my problem is - how to get access to the Dao bean instance created?
In my logic part, I get a hold of the bean as follows:
ClassPathXmlApplicationContext appContex = new ClassPathXmlApplicationContext(new String[] {"spring-hibernate.xml"});
UserUIDDao userUIDDao= (UserUIDDao)appContext.getBean("UserUIDDao");
Problem is - this is a NEW reference to a newly created bean and not the same one created during the spring MVC startup.
So my questions are: how to get a hold of the original bean created by the Spring init process? and - is my setup correct?
the pojos did not change, nor did the hbm.xml files
That's correct.
The configuration is no longer set at hibernate.cfg.xml - the Spring MVC FW loads it's own LocalSessionFactoryBean once I declared it in the XML files (Spring search for xmls as part of the initialization process).
You can choose to use Spring to configure Hibernate (but you could keep your hibernate.cfg.xml).
So I created a separate xml file called spring-hibernate.xml, that has the DB definition, the session factory bean and a hibernate template. To complete it, the xml file also declare the location of the Dao and the hbm files. with hibernate template configured in the xml, there is a bean injection, therefore I changed the Dao files to add getter/setter to a hibernate template property. Then using this - the Dao class may create the db query.
Using Spring's HibernateTemplate is one option, but you could also go template-less and just inject Hibernate's SessionFactory and use sessionFactory.getCurrentSession().
This is actually the officially recommended approach for new projects, check out So should you still use Spring's HibernateTemplate and/or JpaTemplate?? and the javadoc of HibernateTemplate.
Now my problem is - how to get access to the Dao bean instance created?
You inject it where needed (typically, in your services).
In my logic part, I get a hold of the bean as follows (...)
No, don't do this. This "service locator approach" actually defeats the point of a DI container like Spring. Configure Spring to inject your DAOs where needed.
I have an app using Wicket for the presentation layer with CDI/Weld, JPA 2.0, EJB 3.1 etc. (Java EE 6) deployed on GlassFish v3.0.1.
When I try to inject an EJB into a wicket page using #EJB I get the following error:
java.lang.IllegalStateException: Unable to retrieve EntityManagerFactory for unitName
When I try to inject using #Inject, I get the following error:
java.lang.IllegalStateException: Unable to convert ejbRef for ejb UserRepository to a business object of type class
I believe the problem is stemming from JPA. I am using the exact same configuration that I used with a JSF application which worked properly, so I am lost as to what the issue could be. The connection pools are set up properly and pinging correctly through GlassFish, I have included wicket-weld on the classpath and I have even tried using the old Java EE 5 wicketstuff project for wicketstuff-javaeeapi with the same results.
Any help would be appreciated.
If you get the exception:
Unable to retrieve EntityManagerFactory for unitName
It might mean it is not detecting your persistence.xml file. Make sure it's in the WEB-INF\classes\META-INF directory.
You can verify that your app has JPA enabled by going to the Admin Console in GlassFish, go to the Applications section and see if it shows something like [ejb, web, weld, jpa] for your app. If it doesn't show jpa then it's not finding your JPA config file.
Could always try to lookup the EJB via its standard "java:global" name. That should at least let you rule out wicket as a possible source of issues and get you a little closer to a working system.