getting broadleaf to run in a unit test
-
01-07-2021 - |
質問
I'm trying to get Broadleaf Commerce running in a simple JUnit unit test, as a proof of concept to see if I can do basic shopping cart operations, such as adding to cart, updating quantities, and placing an order - without a UI.
The idea to see if I can use a completely different UI with Broadleaf as the backend.
So far, this has been a bit rough to get working (just to get the spring context up and running at all). I'm using Gradle to build my project. The configuration looks as follows:
Test Class:
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration({
"MyTest.xml",
})
public class BltMainTest {
@Test
public void test() {
System.out.println("THIS IS A TEST");
}
}
MyTest.xml:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
">
<import resource="classpath:bl-framework-applicationContext-persistence.xml"/>
<import resource="classpath:bl-framework-applicationContext-entity.xml"/>
<import resource="classpath:bl-framework-applicationContext-workflow.xml"/>
<import resource="classpath:bl-framework-applicationContext.xml"/>
<import resource="classpath:bl-profile-applicationContext.xml"/>
<import resource="classpath:bl-profile-applicationContext-entity.xml"/>
<import resource="classpath:bl-profile-applicationContext-persistence.xml"/>
</beans>
build.gradle excerpts (had to do a bit of a hack to get ehcache to work against Maven Central, not totally sure why):
...
dependencies {
...
compile 'net.sf.ehcache:ehcache-core:2.6.0'
compile('org.broadleafcommerce:broadleaf-framework:1.6.1-GA') {
exclude module: 'ehcache-terracotta'
exclude module: 'ehcache'
}
compile('org.broadleafcommerce:broadleaf-profile:1.6.1-GA') {
exclude module: 'ehcache-terracotta'
exclude module: 'ehcache'
}
...
}
The stack trace I get is rather long, but the bottom most (and I believe relevant) portion is this:
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'blEntityManagerFactorySecureInfo' defined in class path resource [bl-framework-applicationContext-persistence.xml]: Invocation of init method failed; nested exception is java.lang.NullPointerException
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1455)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:519)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:456)
at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:294)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:225)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:291)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:193)
at org.springframework.orm.jpa.EntityManagerFactoryUtils.findEntityManagerFactory(EntityManagerFactoryUtils.java:99)
at org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor.findNamedEntityManagerFactory(PersistenceAnnotationBeanPostProcessor.java:511)
at org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor.findEntityManagerFactory(PersistenceAnnotationBeanPostProcessor.java:493)
at org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor$PersistenceElement.resolveEntityManager(PersistenceAnnotationBeanPostProcessor.java:657)
at org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor$PersistenceElement.getResourceToInject(PersistenceAnnotationBeanPostProcessor.java:630)
at org.springframework.beans.factory.annotation.InjectionMetadata$InjectedElement.inject(InjectionMetadata.java:150)
at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:87)
at org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor.postProcessPropertyValues(PersistenceAnnotationBeanPostProcessor.java:339)
... 55 more
Caused by: java.lang.NullPointerException
at org.hibernate.ejb.Ejb3Configuration.configure(Ejb3Configuration.java:527)
at org.hibernate.ejb.HibernatePersistence.createContainerEntityManagerFactory(HibernatePersistence.java:73)
at org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean.createNativeEntityManagerFactory(LocalContainerEntityManagerFactoryBean.java:268)
at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.afterPropertiesSet(AbstractEntityManagerFactoryBean.java:310)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1514)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1452)
... 69 more
From looking at the class it seems that there is a persistence unit that is not being specified - but I'm not sure where to look to rectify that.
On top of that - the error changes when I change the sequence of the Spring import lines in my config.xml file.
Perhaps I'm approaching this the wrong way, but I'm assuming I should be able to get this working by including the default Broadleaf Spring XMLs in the right sequence - but I've tried a number of them and no dice (some same error, some different, all bad).
Any ideas on how to get this to work?
解決
After digging into this a bit more I did get this working. A few specific things were required:
- The stack trace in the original post was caused by the blPersistenceUnitManager bean being defined in two different Spring context files (not sure how these are being merged in a normal Broadleaf setup), one was overriding the other. The solution was to define one after importing everything that combines the configuration so reads from each of the persistence units needed.
- I had to explicitly use the 3.6.8.Final Hibernate libraries instead of the latest 4.x (some odd error about not being able to figure out what to do with a Map typed column)
- The blPasswordEncoder bean had to be defined
- NOTE: The blCacheManager bean in the example below was required to get around an issue with EHCache: http://jira.broadleafcommerce.org/browse/BLC-599
Here's the guts of the Spring context that finally worked:
<import resource="classpath:bl-common-applicationContext.xml"/>
<import resource="classpath:bl-framework-applicationContext.xml"/>
<import resource="classpath:bl-profile-applicationContext.xml"/>
<import resource="classpath:bl-framework-applicationContext-workflow.xml"/>
<import resource="classpath:bl-framework-applicationContext-persistence.xml"/>
<import resource="classpath:bl-profile-applicationContext-persistence.xml"/>
<import resource="classpath:bl-framework-applicationContext-entity.xml"/>
<import resource="classpath:bl-profile-applicationContext-entity.xml"/>
<bean id="blCacheManager" class="org.broadleafcommerce.common.extensibility.cache.ehcache.MergeEhCacheManagerFactoryBean">
<property name="shared" value="true"/>
</bean>
<bean id="blPersistenceUnitManager" class="org.broadleafcommerce.common.extensibility.jpa.MergePersistenceUnitManager">
<property name="persistenceXmlLocations">
<list>
<value>classpath*:/META-INF/persistence-common.xml</value>
<value>classpath*:/META-INF/persistence-framework.xml</value>
<value>classpath*:/META-INF/persistence-profile.xml</value>
</list>
</property>
</bean>
<bean id="blPasswordEncoder" class="org.springframework.security.authentication.encoding.PlaintextPasswordEncoder"/>
That got me to the point where the unit test builds, runs, the Hibernate environment fires up and I can @Resource() stuff, etc. Not sure how functional it all is yet, but I figured I'd post the answer to this question since I got that far.