PDA

View Full Version : use jbpm31 module in test


akakunin
Apr 14th, 2006, 04:29 AM
Hello!
May be somebody may help me. I'm using spring-jbpm31 module (build from last sources) for may BPM-based tool.

For all process we have in my system we write unit-tests. All this unit-tests are inherited from one class - here is some part of code:


public class AbstractProcessTest extends TestCase {
/// application context
private ApplicationContext m_ac;

/// task management session
TaskMgmtSession m_tms;

/// tested process definition
ProcessDefinition m_processDef;

protected void setUp() throws Exception {
m_ac = new FileSystemXmlApplicationContext("src/config.files/applicationContext.xml");
assertNotNull(m_ac);

JbpmConfiguration jbpmConfiguration = (JbpmConfiguration)m_ac.getBean("jbpmConfiguration");
assertNotNull(jbpmConfiguration);

JbpmContext jbpmContext = jbpmConfiguration.createJbpmContext();
assertNotNull(jbpmContext);

m_tms = JbpmContext.getCurrentJbpmContext().getTaskMgmtSes sion();
assertNotNull(m_tms);
}

protected void tearDown() throws Exception {
m_processDef = null;
m_tms = null;
m_ac = null;

/// close jbpm context
if (JbpmContext.getCurrentJbpmContext() != null) {
JbpmContext.getCurrentJbpmContext().close();
}
}


So, tis code creates application context from, creates jbpm configuration, gets the context from it and then in test case I load process definition into this context and use it.

After making test I close context.

Everything work fine.... only for one test - then I try to run two test on second setUp I've got an error:

org.springframework.beans.factory.BeanCreationExce ption: Error creating bean with name 'jbpmConfiguration' defined in file [D:\work\processes\workspace\EmDevProcesses\src\con fig.files\applicationContext.xml]: Initialization of bean failed; nested exception is java.lang.IllegalArgumentException: a beanFactoryReference already exists for key jbpmConfiguration
java.lang.IllegalArgumentException: a beanFactoryReference already exists for key jbpmConfiguration
at org.springmodules.workflow.jbpm31.JbpmFactoryLocat or.addToMap(JbpmFactoryLocator.java:108)
at org.springmodules.workflow.jbpm31.JbpmFactoryLocat or.setBeanFactory(JbpmFactoryLocator.java:76)
at org.springmodules.workflow.jbpm31.LocalJbpmConfigu rationFactoryBean.setBeanFactory(LocalJbpmConfigur ationFactoryBean.java:70)
at org.springframework.beans.factory.support.Abstract AutowireCapableBeanFactory.initializeBean(Abstract AutowireCapableBeanFactory.java:818)
at org.springframework.beans.factory.support.Abstract AutowireCapableBeanFactory.createBean(AbstractAuto wireCapableBeanFactory.java:418)
at org.springframework.beans.factory.support.Abstract BeanFactory.getBean(AbstractBeanFactory.java:241)
at org.springframework.beans.factory.support.Abstract BeanFactory.getBean(AbstractBeanFactory.java:152)
at org.springframework.beans.factory.support.DefaultL istableBeanFactory.preInstantiateSingletons(Defaul tListableBeanFactory.java:247)
at org.springframework.context.support.AbstractApplic ationContext.refresh(AbstractApplicationContext.ja va:331)
at org.springframework.context.support.FileSystemXmlA pplicationContext.<init>(FileSystemXmlApplicationContext.java:89)
at org.springframework.context.support.FileSystemXmlA pplicationContext.<init>(FileSystemXmlApplicationContext.java:74)
at org.springframework.context.support.FileSystemXmlA pplicationContext.<init>(FileSystemXmlApplicationContext.java:65)
at ru.emdev.EmDevProcesses.tests.AbstractProcessTest. setUp(AbstractProcessTest.java:42)
at ru.emdev.EmDevProcesses.tests.ToBuyProcessTestCase .setUp(ToBuyProcessTestCase.java:18)
at junit.framework.TestCase.runBare(TestCase.java:125 )
at junit.framework.TestResult$1.protect(TestResult.ja va:106)
at junit.framework.TestResult.runProtected(TestResult .java:124)
at junit.framework.TestResult.run(TestResult.java:109 )
at junit.framework.TestCase.run(TestCase.java:118)
at junit.framework.TestSuite.runTest(TestSuite.java:2 08)
at junit.framework.TestSuite.run(TestSuite.java:203)
at junit.framework.TestSuite.runTest(TestSuite.java:2 08)
at junit.framework.TestSuite.run(TestSuite.java:203)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRu nner.runTests(RemoteTestRunner.java:478)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRu nner.run(RemoteTestRunner.java:344)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRu nner.main(RemoteTestRunner.java:196)


So, seems my jbpmConfiguration keep somethere (even if I created new application context) and I can not create new one

But may be somebody know how it is possible to kill it?

PS. Additionally here is my applicationContext.xml

<beans>
<!-- Database settings -->
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerD ataSource">
<property name="driverClassName" value="org.hsqldb.jdbcDriver"/>
<property name="url" value="jdbc:hsqldb:mem:.;sql.enforce_strict_size=true"/>
<property name="username" value="sa"/>
<property name="password" value=""/>
</bean>

<!-- hibernate settings -->
<bean id="hibernateSessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFac toryBean">
<property name="dataSource" ref="dataSource"></property>
<property name="mappingLocations">
<list>
<value>classpath*:/org/jbpm/**/*.hbm.xml</value>
</list>
</property>
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">org.hibernate.dialect.HSQLDialect</prop>
<prop key="hibernate.show_sql">true</prop>
</props>
</property>

<property name="schemaUpdate" value="true"/>
</bean>

<bean id="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransa ctionManager">
<property name="sessionFactory">
<ref local="hibernateSessionFactory"/>
</property>
</bean>


<!-- JBPM Configuration -->
<bean id="jbpmConfiguration" class="org.springmodules.workflow.jbpm31.LocalJbpmConfigu rationFactoryBean">
<property name="sessionFactory" ref="hibernateSessionFactory"/>
<property name="configuration" value="classpath:/ru/emdev/EmForge/jbpm.cfg.xml"/>
</bean>
</beans>


Seems it is more then standard :)

Does anybody have any suggestions?

Costin Leau
Apr 15th, 2006, 02:45 PM
I think there is a problem with your test case. Since jbpm uses a lot of static references the integration code is forced to use static calls and variables. The JbpmFactoryLocator is used to discover the jbpmSessionFactory and place them in a static context to be used for the Action injection.
Even though you are closing the jbpm context you are not closing the Spring application context.
I recommend you take a look at the Spring test suite which will load your application context and cache it between your tests. Take a look at the test suite from jbpm integration for some examples.

akakunin
Apr 18th, 2006, 10:55 AM
Costin, thank you very much for your advice. I looked into Spring Test Framework morfe detail and finally understand a little bit more how some Jbpm31 module tests work.

So, I rewrote my basic class to use Spring Test-Framework and JbpmTemplate like this:


package ru.emdev.EmDevProcesses.tests;

import java.util.List;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.jbpm.graph.def.Node;
import org.jbpm.graph.exe.ProcessInstance;
import org.jbpm.graph.exe.Token;
import org.jbpm.taskmgmt.exe.TaskInstance;
import org.springframework.test.AbstractDependencyInjecti onSpringContextTests;
import org.springmodules.workflow.jbpm31.JbpmTemplate;

import ru.emdev.ProcessManager.bean.ProcessDefBean;
import ru.emdev.ProcessManager.bean.TaskBean;

/** Basic class for Process Tests
*
*/
public class AbstractProcessTest extends AbstractDependencyInjectionSpringContextTests {
private static Log log = LogFactory.getLog(AbstractProcessTest.class);

/// template class to store jbpm template
/// setTemplate implemented in every test case to get
/// the exactly template we are going to test
JbpmTemplate m_template;

protected String[] getConfigLocations() {
return new String[] {"ru/emdev/EmDevProcesses/tests/applicationContext.xml"};
}

/** Starts New Process
*
* This function starts new process for m_processDef,
* assigns description and process owner
* @param i_description - description for created process
* @param i_user - owner for created process
*
* @return Start Task Instance for created Process
*/
protected TaskInstance startProcess(String i_description,
String i_user) {
assertNotNull(i_description);
assertNotNull(i_user);

log.info("Start new Process");

ProcessInstance process = m_template.getProcessDefinition().createProcessIns tance();
assertNotNull(process);

//get start task
TaskInstance startTask = process.getTaskMgmtInstance().createStartTaskInsta nce();
assertNotNull(startTask);

// now, assign initial values to the task
startTask.setVariable(TaskBean.DESCRIPTION_VARIABL E, i_description);
startTask.setVariable(ProcessDefBean.OWNER_VARIABL E, i_user);

return startTask;
}

/** Ends the specified task and check next task assignment
*
* @param i_prevTask - task to end
* @param i_nextTaskOwner- owner of next assigned task
* @param i_nextTaskName - name of the next task
*
* @return next task
*/
protected TaskInstance endTask(TaskInstance i_prevTask,
String i_nextTaskOwner,
String i_nextTaskName) {
assertNotNull(i_prevTask);
assertNotNull(i_nextTaskOwner);
assertNotNull(i_nextTaskName);

log.info("Finish Task " + i_prevTask.getName());
// end task
i_prevTask.end();

// get current task
TaskInstance task = getOneTask(i_nextTaskOwner, i_nextTaskName);

// check next node
checkNode(task.getToken(), i_nextTaskName);

return task;
}

/** Ends the specified task by specified transition
* and check next task assignment
*
* @param i_transitionName - transition to leave the node
* @param i_prevTask - task to end
* @param i_nextTaskOwner- owner of next assigned task
* @param i_nextTaskName - name of the next task
*
* @return next task
*/
protected TaskInstance endTask(TaskInstance i_prevTask,
String i_transitionName,
String i_nextTaskOwner,
String i_nextTaskName) {
assertNotNull(i_prevTask);
assertNotNull(i_transitionName);
assertNotNull(i_nextTaskOwner);
assertNotNull(i_nextTaskName);

// end task
i_prevTask.end(i_transitionName);

// check next node
checkNode(i_prevTask.getToken(), i_nextTaskName);

// get current task
TaskInstance task = getOneTask(i_nextTaskOwner, i_nextTaskName);

return task;
}
/** check the node for specified token
*
* @param i_token token to check
* @param i_nodeName - name of expected node
*/
protected void checkNode(Token i_token, String i_nodeName) {
assertNotNull(i_token);
assertNotNull(i_nodeName);

Node node = i_token.getNode();
assertNotNull(node);

assertEquals(i_nodeName, node.getName());
}

/** Checks that specified user has only one task with specified name and returns this task
*
* @param i_user - user to check
* @param i_taskName - expected task name
*
* @return expected task
*/
protected TaskInstance getOneTask(String i_user, String i_taskName) {
assertNotNull(m_template);
assertNotNull(i_user);
assertNotNull(i_taskName);

List tasks = m_template.findTaskInstances(i_user);
assertNotNull(tasks);

assertEquals(i_user + " should have only 1 task",
1,
tasks.size());

TaskInstance task = (TaskInstance)tasks.get(0);
assertNotNull(task);

//check task instance name
assertEquals(i_taskName, task.getName());

return task;
}

/** Checks that specified user has not active tasks assigned to him
*
* @param i_user - user to check
*/
protected void checkNoTasks(String i_user) {
assertNotNull(m_template);
assertNotNull(i_user);

// user akakunin should have no tasks
List tasks = m_template.findTaskInstances(i_user);
assertEquals(i_user + " should have no task",
0,
tasks.size());
}
}


In inherited test I just implement required setter to set tested template like:

class ToDoProcessTest extends AbstractProcessTest {
setToDoTemplate(JbpmTemplate i_template) {
m_template = i_template;
}

public void testProcess() {
assertNotNull(m_template);

//get start task
TaskInstance startTask = startProcess("Do something!", "somebody");

TaskInstance nextTask = endTask(startTask, "somebody", "Assign ToDo");

......
}


Everything works quite well, I've got template, may start new process instance, set variable, finish start task, I can see that my assigner was called and next task was assigned to 'somebody'... but then I try to get active tasks for this 'somebody' via JbpmTemplate::findTaskInstance I've got nothing :(

I looked into JbpmTemplate code and found that all of these methods are called in doInJbpm wrappers... but my process instance was created from process definition without any these wrappers - may be this is a problem?

It really seems that my process instance lives in another JbpmContext/HibernateSession then code called in JbpmTemplate's doInJbpm wrapper - but if it so - how to change it?

I feel that I'm near to setup my process testing properly according to Spring Framework, but still need to fix some problem. Does you have any advices or suggestions?

Thank you

Costin Leau
Apr 19th, 2006, 07:31 AM
Each process instance has an id - you can use that to get a hold of an instance. If you need something else then the utility methods on the JbpmTemplate, use the Callback and there get a hold of the instance and call the methods you need.
Like in most bpm solutions, the state is persisted and one has to request the engine for an instance each time he/she want to work on it, instead of carrying the instance around.

akakunin
Apr 24th, 2006, 08:52 AM
Costin,
Thank you for your answers.
I looked more into my tests and usage of JbpmTemplate and found that I was write... my code (started from m_template.getProcessDefinition().createInstance() ) lived in one JbpmContext (to say truth it works without any JbpmContext!) and code performed in JbpmTemplate lived in another - everytime created context...

It is not very comfortable, because in massive usage of Jbpm operations (like in my tests) I should wrap WHOLE code with m_template.execute() wrapper and use bpm context I've got...

So, in this case usage of JbpmTemplate is not very comfortable and only one reason that I can see - it solves initial problem with multiple context creation in one test suite...

Maybe you have some ideas about better organization for Jbpm processes testing via junit with using Spring-Framework?

akakunin
Apr 24th, 2006, 09:29 AM
OK, may be I need to read some more information abotu usage templates, tests and so on under Spring... but I found another problem trying to test my processes with jbpm31 spring module.

So, here is basic class for testing processes:

package ru.emdev.EmDevProcesses.tests;

import ...;

/*AbstractTransactionalDataSourceSpringContextTests */
/** Basic class for Process Tests
*
*/
public class AbstractProcessTest extends AbstractTransactionalDataSourceSpringContextTests {
private static Log log = LogFactory.getLog(AbstractProcessTest.class);

/// template class to store jbpm template
/// setTemplate implemented in every test case to get
/// the exactly template we are going to test
JbpmTemplate m_template;

JbpmContext m_jbpmContext;

/** Special call-back interface for performing tests
*
*/
public interface ProcessTestCallback {
public void doTest();
};


/** this function is used for performing test specified in call back class
*
* This method is required for placing whole test into Jbpm context
*
* @param i_callBack
*/
protected void executeTest(final ProcessTestCallback i_callBack) {
m_template.execute(new JbpmCallback() {

public Object doInJbpm(JbpmContext context) {
m_jbpmContext = context;

try {
i_callBack.doTest();
} finally {
m_jbpmContext = null;
}

return null;
}
});
}


protected String[] getConfigLocations() {
return new String[] {"ru/emdev/EmDevProcesses/tests/applicationContext.xml"};
}

/** Starts New Process
*
* This function starts new process for m_processDef,
* assigns description and process owner
* @param i_description - description for created process
* @param i_user - owner for created process
*
* @return Start Task Instance for created Process
*/
protected TaskInstance startProcess(String i_description,
String i_user) {
assertNotNull(m_jbpmContext);
assertNotNull(i_description);
assertNotNull(i_user);

log.info("Start new Process");

/*
ProcessInstance process = (ProcessInstance)m_template.execute(new JbpmCallback() {

public Object doInJbpm(JbpmContext context) {
context.getGraphSession().saveProcessDefinition(m_ template.getProcessDefinition());

ProcessDefinition processDef = context.getGraphSession().findLatestProcessDefinit ion(m_template.getProcessDefinition().getName());
ProcessInstance process = processDef.createProcessInstance();

return process;
}
});
*/


m_jbpmContext.getGraphSession().saveProcessDefinit ion(m_template.getProcessDefinition());

ProcessDefinition processDef = m_jbpmContext.getGraphSession().findLatestProcessD efinition(m_template.getProcessDefinition().getNam e());
ProcessInstance process = processDef.createProcessInstance();


assertNotNull(process);


//get start task
TaskInstance startTask = process.getTaskMgmtInstance().createStartTaskInsta nce();
assertNotNull(startTask);

// now, assign initial values to the task
startTask.setVariable(JbpmTaskImpl.DESCRIPTION_VAR IABLE, i_description);
startTask.setVariable(JbpmProcessDefImpl.OWNER_VAR IABLE, i_user);

return startTask;
}

/** Ends the specified task and check next task assignment
*
* @param i_prevTask - task to end
* @param i_nextTaskOwner- owner of next assigned task
* @param i_nextTaskName - name of the next task
*
* @return next task
*/
protected TaskInstance endTask(final TaskInstance i_prevTask,
String i_nextTaskOwner,
String i_nextTaskName) {
assertNotNull(i_prevTask);
assertNotNull(i_nextTaskOwner);
assertNotNull(i_nextTaskName);

log.info("Finish Task " + i_prevTask.getName());
// end task
i_prevTask.end();

/*
m_template.execute(new JbpmCallback() {

public Object doInJbpm(JbpmContext context) {
context.save(i_prevTask);

return null;
}
});
*/


// get current task
TaskInstance task = getOneTask(i_nextTaskOwner, i_nextTaskName);

// check next node
checkNode(task.getToken(), i_nextTaskName);

return task;
}

/** Ends the specified task by specified transition
* and check next task assignment
*
* @param i_transitionName - transition to leave the node
* @param i_prevTask - task to end
* @param i_nextTaskOwner- owner of next assigned task
* @param i_nextTaskName - name of the next task
*
* @return next task
*/
protected TaskInstance endTask(TaskInstance i_prevTask,
String i_transitionName,
String i_nextTaskOwner,
String i_nextTaskName) {
assertNotNull(i_prevTask);
assertNotNull(i_transitionName);
assertNotNull(i_nextTaskOwner);
assertNotNull(i_nextTaskName);

// end task
i_prevTask.end(i_transitionName);

//m_jbpmContext.save(i_prevTask);

// check next node
checkNode(i_prevTask.getToken(), i_nextTaskName);

// get current task
TaskInstance task = getOneTask(i_nextTaskOwner, i_nextTaskName);

return task;
}
/** check the node for specified token
*
* @param i_token token to check
* @param i_nodeName - name of expected node
*/
protected void checkNode(Token i_token, String i_nodeName) {
assertNotNull(i_token);
assertNotNull(i_nodeName);

Node node = i_token.getNode();
assertNotNull(node);

assertEquals(i_nodeName, node.getName());
}

/** Checks that specified user has only one task with specified name and returns this task
*
* @param i_user - user to check
* @param i_taskName - expected task name
*
* @return expected task
*/
protected TaskInstance getOneTask(String i_user, String i_taskName) {
assertNotNull(m_jbpmContext);
assertNotNull(i_user);
assertNotNull(i_taskName);

//List tasks = m_template.findTaskInstances(i_user);
List tasks = m_jbpmContext.getTaskMgmtSession().findTaskInstanc es(i_user);
assertNotNull(tasks);

assertEquals(i_user + " should have only 1 task",
1,
tasks.size());

TaskInstance task = (TaskInstance)tasks.get(0);
assertNotNull(task);

//check task instance name
assertEquals(i_taskName, task.getName());

return task;
}

/** Checks that specified user has not active tasks assigned to him
*
* @param i_user - user to check
*/
protected void checkNoTasks(String i_user) {
assertNotNull(m_jbpmContext);
assertNotNull(i_user);

// user akakunin should have no tasks
//List tasks = m_template.findTaskInstances(i_user);
List tasks = m_jbpmContext.getTaskMgmtSession().findTaskInstanc es(i_user);

assertEquals(i_user + " should have no task",
0,
tasks.size());
}
}


What actually it did:

Inherited from AbstractTransactionalDataSourceSpringContextTests for transactions support
Declare special callback class for executing test code
Declare function, that executes specified in callback code inside JbpmContext. Before execution it gets JbpmContext variable to use it in test, and after execution it set it to null


Test derived from this class looks like:

package ru.emdev.EmDevProcesses.tests;

public class ToDoProcessTestCase extends AbstractProcessTest {
public void setTodoTemplate(JbpmTemplate i_template) {
m_template = i_template;
}

public void testShortWay() {
executeTest(new ProcessTestCallback() {
public void doTest() {

//get start task
TaskInstance startTask = startProcess("Do something!", "somebody");

TaskInstance nextTask = endTask(startTask, "somebody", "Assign ToDo");
assertNotNull(nextTask);

// ...
// do something extra
// ...
}
});
}

public void testReject() {
executeTest(new ProcessTestCallback() {
public void doTest() {

//get start task
TaskInstance startTask = startProcess("Do something!", "somebody");

TaskInstance nextTask = endTask(startTask, "somebody", "Assign ToDo");
assertNotNull(nextTask);

// ...
// do something extra
// ...
}});
}
}


So, it work quite fine and solves all problem I had before:

No problem with jbpm configuration I initially had
Whole test code is performed in one JbpmContext, so it works


In my console I can see followed strings:

5989 [main] INFO ru.emdev.EmDevProcesses.tests.ToDoProcessTestCase - Began transaction (1): transaction manager [org.springframework.orm.hibernate3.HibernateTransa ctionManager@1570c24]; default rollback = true
5989 [main] INFO ru.emdev.EmDevProcesses.tests.AbstractProcessTest - Start new Process
6560 [main] INFO ru.emdev.EmDevProcesses.tests.ToDoProcessTestCase - Rolled back transaction after test execution


So, seems transactions works... but.... I have no test isolation! :( Task created,assigned to somebody and not closed in one test still assigned in another :(

Oh... seems all these staff should make our life easily... But I already spent too much time trying to make my working non-spring based working tests working in spring-based environment... May be I do something totally wronge?
Are somethere any workable example available?

Thank you for any advice!

Costin Leau
Apr 25th, 2006, 02:37 AM
Alexey, your problem is with Jbpm then Spring Modules jbpm support. Spring Modules offers just a wrapper around Jbpm. I suggest you take this issue with jbpm mailing lists. Try for example to acheive the same functionality with plain jbpm and see how easy/complicated it is compared to the one you have right now.

ghettojava
Jul 5th, 2006, 04:23 PM
I am having a similiar issue, I am trying to use the unit tests from the cvs.
For example when I run JbpmObjectFactoryTests (from cvs)
I get the stracktrace below. Oddly enough the JbpmFactoryLocatorTests works produces no errors or exceptions :

Do I have explicitly to null out jbpmConfiguration?


testCreateObject(com.aaxistechnologies.workflow.Jb pmObjectFactoryTest) Time elapsed: 0.276 sec <<< ERROR!
org.springframework.beans.factory.BeanCreationExce ption: Error creating bean with name 'jbpmConfiguration' defined in class path resource [applicationContext.xml]: Initialization of bean failed; nested exception is java.lang.IllegalArgumentException: a beanFactoryReference already exists for key jbpmConfiguration
Caused by: java.lang.IllegalArgumentException: a beanFactoryReference already exists for key jbpmConfiguration
at org.springmodules.workflow.jbpm31.JbpmFactoryLocat or.addToMap(JbpmFactoryLocator.java:108)
at org.springmodules.workflow.jbpm31.JbpmFactoryLocat or.setBeanFactory(JbpmFactoryLocator.java:76)
at org.springmodules.workflow.jbpm31.LocalJbpmConfigu rationFactoryBean.setBeanFactory(LocalJbpmConfigur ationFactoryBean.java:70)
at org.springframework.beans.factory.support.Abstract AutowireCapableBeanFactory.initializeBean(Abstract AutowireCapableBeanFactory.java:863)
at org.springframework.beans.factory.support.Abstract AutowireCapableBeanFactory.createBean(AbstractAuto wireCapableBeanFactory.java:393)
at org.springframework.beans.factory.support.Abstract BeanFactory.getBean(AbstractBeanFactory.java:257)
at org.springframework.beans.factory.support.Abstract BeanFactory.getBean(AbstractBeanFactory.java:168)
at org.springframework.beans.factory.support.DefaultL istableBeanFactory.preInstantiateSingletons(Defaul tListableBeanFactory.java:248)
at org.springframework.context.support.AbstractApplic ationContext.refresh(AbstractApplicationContext.ja va:332)
at org.springframework.context.support.ClassPathXmlAp plicationContext.<init>(ClassPathXmlApplicationContext.java:92)
at org.springframework.context.support.ClassPathXmlAp plicationContext.<init>(ClassPathXmlApplicationContext.java:77)
at org.springframework.test.AbstractSpringContextTest s.loadContextLocations(AbstractSpringContextTests. java:130)
at org.springframework.test.AbstractDependencyInjecti onSpringContextTests.loadContextLocations(Abstract DependencyInjectionSpringContextTests.java:224)
at org.springframework.test.AbstractSpringContextTest s.getContext(AbstractSpringContextTests.java:110)
at org.springframework.test.AbstractDependencyInjecti onSpringContextTests.setUp(AbstractDependencyInjec tionSpringContextTests.java:192)
at junit.framework.TestCase.runBare(TestCase.java:125 )
at org.springframework.test.ConditionalTestCase.runBa re(ConditionalTestCase.java:69)
at junit.framework.TestResult$1.protect(TestResult.ja va:106)
at junit.framework.TestResult.runProtected(TestResult .java:124)
at junit.framework.TestResult.run(TestResult.java:109 )
at junit.framework.TestCase.run(TestCase.java:118)
at junit.framework.TestSuite.runTest(TestSuite.java:2 08)
at junit.framework.TestSuite.run(TestSuite.java:203)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Nativ e Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(Native MethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(De legatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:585)
at org.apache.maven.surefire.junit.JUnitTestSet.execu te(JUnitTestSet.java:210)
at org.apache.maven.surefire.suite.AbstractDirectoryT estSuite.executeTestSet(AbstractDirectoryTestSuite .java:135)
at org.apache.maven.surefire.suite.AbstractDirectoryT estSuite.execute(AbstractDirectoryTestSuite.java:1 22)
at org.apache.maven.surefire.Surefire.run(Surefire.ja va:129)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Nativ e Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(Native MethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(De legatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:585)
at org.apache.maven.surefire.booter.SurefireBooter.ru nSuitesInProcess(SurefireBooter.java:225)
at org.apache.maven.surefire.booter.SurefireBooter.ma in(SurefireBooter.java:747)

testHasObject(com.aaxistechnologies.workflow.JbpmO bjectFactoryTest) Time elapsed: 0.158 sec <<< ERROR!
org.springframework.beans.factory.BeanCreationExce ption: Error creating bean with name 'jbpmConfiguration' defined in class path resource [applicationContext.xml]: Initialization of bean failed; nested exception is java.lang.IllegalArgumentException: a beanFactoryReference already exists for key jbpmConfiguration
Caused by: java.lang.IllegalArgumentException: a beanFactoryReference already exists for key jbpmConfiguration
at org.springmodules.workflow.jbpm31.JbpmFactoryLocat or.addToMap(JbpmFactoryLocator.java:108)
at org.springmodules.workflow.jbpm31.JbpmFactoryLocat or.setBeanFactory(JbpmFactoryLocator.java:76)
at org.springmodules.workflow.jbpm31.LocalJbpmConfigu rationFactoryBean.setBeanFactory(LocalJbpmConfigur ationFactoryBean.java:70)
at org.springframework.beans.factory.support.Abstract AutowireCapableBeanFactory.initializeBean(Abstract AutowireCapableBeanFactory.java:863)
at org.springframework.beans.factory.support.Abstract AutowireCapableBeanFactory.createBean(AbstractAuto wireCapableBeanFactory.java:393)
at org.springframework.beans.factory.support.Abstract BeanFactory.getBean(AbstractBeanFactory.java:257)
at org.springframework.beans.factory.support.Abstract BeanFactory.getBean(AbstractBeanFactory.java:168)
at org.springframework.beans.factory.support.DefaultL istableBeanFactory.preInstantiateSingletons(Defaul tListableBeanFactory.java:248)
at org.springframework.context.support.AbstractApplic ationContext.refresh(AbstractApplicationContext.ja va:332)
at org.springframework.context.support.ClassPathXmlAp plicationContext.<init>(ClassPathXmlApplicationContext.java:92)
at org.springframework.context.support.ClassPathXmlAp plicationContext.<init>(ClassPathXmlApplicationContext.java:77)
at org.springframework.test.AbstractSpringContextTest s.loadContextLocations(AbstractSpringContextTests. java:130)
at org.springframework.test.AbstractDependencyInjecti onSpringContextTests.loadContextLocations(Abstract DependencyInjectionSpringContextTests.java:224)
at org.springframework.test.AbstractSpringContextTest s.getContext(AbstractSpringContextTests.java:110)
at org.springframework.test.AbstractDependencyInjecti onSpringContextTests.setUp(AbstractDependencyInjec tionSpringContextTests.java:192)
at junit.framework.TestCase.runBare(TestCase.java:125 )
at org.springframework.test.ConditionalTestCase.runBa re(ConditionalTestCase.java:69)
at junit.framework.TestResult$1.protect(TestResult.ja va:106)
at junit.framework.TestResult.runProtected(TestResult .java:124)
at junit.framework.TestResult.run(TestResult.java:109 )
at junit.framework.TestCase.run(TestCase.java:118)
at junit.framework.TestSuite.runTest(TestSuite.java:2 08)
at junit.framework.TestSuite.run(TestSuite.java:203)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Nativ e Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(Native MethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(De legatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:585)
at org.apache.maven.surefire.junit.JUnitTestSet.execu te(JUnitTestSet.java:210)
at org.apache.maven.surefire.suite.AbstractDirectoryT estSuite.executeTestSet(AbstractDirectoryTestSuite .java:135)
at org.apache.maven.surefire.suite.AbstractDirectoryT estSuite.execute(AbstractDirectoryTestSuite.java:1 22)
at org.apache.maven.surefire.Surefire.run(Surefire.ja va:129)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Nativ e Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(Native MethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(De legatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:585)
at org.apache.maven.surefire.booter.SurefireBooter.ru nSuitesInProcess(SurefireBooter.java:225)
at org.apache.maven.surefire.booter.SurefireBooter.ma in(SurefireBooter.java:747)

ghettojava
Jul 7th, 2006, 02:21 PM
Just to add some thoughts. I think my main issue is with the way junit creates new objects for each test method , it does not seem to release the application context between tests. Conversly, making the applicationContext static in a parent test class didn't make the error go away either. Maybe I'll have to skip the tests for now and see if I can get it working as an app.

Costin Leau
Jul 9th, 2006, 02:45 PM
You have to clear the map or have the bean static - the problem is that jbpm in its core uses static fields so the support classes have to be statical also - when using junits (and new objects are created) the static fields create subtle errors - if you look at the trace two values are registered for the same key inside a static map:

Caused by: java.lang.IllegalArgumentException: a beanFactoryReference already exists for key jbpmConfiguration
at org.springmodules.workflow.jbpm31.JbpmFactoryLocat or.addToMap(JbpmFactoryLocator.java:108)
at org.springmodules.workflow.jbpm31.JbpmFactoryLocat or.setBeanFactory(JbpmFactoryLocator.java:76)

Can you post some snippets from your tests?

ghettojava
Jul 10th, 2006, 02:18 PM
This is an example test that doesn't do anything but fails because of the beanfactory exception:


package com.ccc;

/**
* Created by IntelliJ IDEA.
* User: xaymaca
* Date: Jul 10, 2006
* Time: 2:01:25 PM
*/
public class JBPMExampleTest extends SpringTestBase {


public JBPMExampleTest() throws Exception {
}


public void testThis() {

assertTrue(true);
}

public void testThat() {
assertTrue(true);
}

}


it inherits from this base class:




public class SpringTestBase extends AbstractDependencyInjectionSpringContextTests {
static ApplicationContext ctx ;

static {
String[] configLocations = new String[] { "applicationContext.xml" };
ctx = new ClassPathXmlApplicationContext(configLocations);


}


public SpringTestBase() throws Exception {
//onSetUpBeforeTransaction();
}



protected String[] getConfigLocations() {
return new String[] { "applicationContext.xml" };
}
:


public static ApplicationContext getCtx() {
return ctx;
}
}


Let me know if you want to see my applicationContext.xml file as well.

Even this test throws:



10 Jul 2006 14:15:48 INFO org.jbpm.JbpmConfiguration - using jbpm configuration resource 'jbpm.cfg.xml'
10 Jul 2006 14:15:51 INFO org.springmodules.workflow.jbpm31.LocalJbpmConfigu rationFactoryBean - creating JbpmConfiguration from resource class path resource [jbpm.cfg.xml]
10 Jul 2006 14:15:51 INFO org.springmodules.workflow.jbpm31.LocalJbpmConfigu rationFactoryBean - using given Hibernate session factory
10 Jul 2006 14:15:51 INFO org.springmodules.workflow.jbpm31.LocalJbpmConfigu rationFactoryBean - creating schema
DummyActionHandler constructor
10 Jul 2006 14:15:57 INFO com.aaxistechnologies.JBPMExampleTest - Loading config for: applicationContext.xml

org.springframework.beans.factory.BeanCreationExce ption: Error creating bean with name 'JbpmConfiguration' defined in class path resource [applicationContext.xml]: Initialization of bean failed; nested exception is java.lang.IllegalArgumentException: a beanFactoryReference already exists for key JbpmConfiguration
Caused by: java.lang.IllegalArgumentException: a beanFactoryReference already exists for key JbpmConfiguration
at org.springmodules.workflow.jbpm31.JbpmFactoryLocat or.addToMap(JbpmFactoryLocator.java:108)
at org.springmodules.workflow.jbpm31.JbpmFactoryLocat or.setBeanFactory(JbpmFactoryLocator.java:76)
at org.springmodules.workflow.jbpm31.LocalJbpmConfigu rationFactoryBean.setBeanFactory(LocalJbpmConfigur ationFactoryBean.java:70)

ghettojava
Jul 10th, 2006, 03:39 PM
Ok, got an idea from another post (about finding the ApplicationContext in a webapp) of having my base Test class implement ApplicationContextAware and removed that static { } block. I don't know why but this fixed my duplication problem. I can once again see the "normal" errors in my unit tests, though. After fixing those I'm passing my tests with flying colors!
Thanks,
GJ