今天按照jbpm开发指南里的数据库持久存储方式存储流程定义文件,一直出现插入字段错误,原来是jbpm3.2.2在mysql中字段的类型的错误.
错误如下:
警告: SQL Error: 1406, SQLState: 22001
2008-6-6 18:20:58 org.hibernate.util.JDBCExceptionReporter logExceptions
严重: Data too long for column 'ISTERMINATIONIMPLICIT_' at row 1
2008-6-6 18:20:58 org.hibernate.util.JDBCExceptionReporter logExceptions
警告: SQL Error: 1406, SQLState: 22001
2008-6-6 18:20:58 org.hibernate.util.JDBCExceptionReporter logExceptions
严重: Data too long for column 'ISASYNC_' at row 1
2008-6-6 18:20:58 org.jbpm.persistence.db.DbPersistenceService commit
严重: hibernate commit failed
org.hibernate.exception.DataException: could not insert: [org.jbpm.graph.node.StartState]
at org.hibernate.exception.SQLStateConverter.convert(SQLStateConverter.java:77)
at org.hibernate.exception.JDBCExceptionHelper.convert(JDBCExceptionHelper.java:43)
at org.hibernate.id.insert.AbstractReturningDelegate.performInsert(AbstractReturningDelegate.java:40)
at org.hibernate.persister.entity.AbstractEntityPersister.insert(AbstractEntityPersister.java:2158)
at org.hibernate.persister.entity.AbstractEntityPersister.insert(AbstractEntityPersister.java:2638)
at org.hibernate.action.EntityIdentityInsertAction.execute(EntityIdentityInsertAction.java:48)
at org.hibernate.engine.ActionQueue.execute(ActionQueue.java:248)
at org.hibernate.event.def.AbstractSaveEventListener.performSaveOrReplicate(AbstractSaveEventListener.java:298)
at org.hibernate.event.def.AbstractSaveEventListener.performSave(AbstractSaveEventListener.java:181)
at org.hibernate.event.def.AbstractSaveEventListener.saveWithGeneratedId(AbstractSaveEventListener.java:107)
at org.hibernate.event.def.DefaultSaveOrUpdateEventListener.saveWithGeneratedOrRequestedId(DefaultSaveOrUpdateEventListener.java:187)
at org.hibernate.event.def.DefaultSaveOrUpdateEventListener.entityIsTransient(DefaultSaveOrUpdateEventListener.java:172)
at org.hibernate.event.def.DefaultSaveOrUpdateEventListener.performSaveOrUpdate(DefaultSaveOrUpdateEventListener.java:94)
at org.hibernate.event.def.DefaultSaveOrUpdateEventListener.onSaveOrUpdate(DefaultSaveOrUpdateEventListener.java:70)
at org.hibernate.impl.SessionImpl.fireSaveOrUpdate(SessionImpl.java:507)
at org.hibernate.impl.SessionImpl.saveOrUpdate(SessionImpl.java:499)
at org.hibernate.engine.CascadingAction$1.cascade(CascadingAction.java:218)
接下去我想直接在mysql里修改字段类型,但是竟然不能保存,到现在也不知道为什么.用sql语句就可以.
修改的sql语句:
ALTER TABLE JBPM_PROCESSDEFINITION MODIFY ISTERMINATIONIMPLICIT_ TINYINT(1);
ALTER TABLE JBPM_ACTION MODIFY ISASYNC_ TINYINT(1);
ALTER TABLE JBPM_ACTION MODIFY ISPROPAGATIONALLOWED_ TINYINT(1);
ALTER TABLE JBPM_NODE MODIFY ISASYNC_ TINYINT(1);
ALTER TABLE JBPM_NODE MODIFY ISASYNCEXCL_ TINYINT(1);
ALTER TABLE JBPM_NODE MODIFY CREATETASKS_ TINYINT(1);
ALTER TABLE JBPM_NODE MODIFY ENDTASKS_ TINYINT(1);
ALTER TABLE JBPM_PROCESSINSTANCE MODIFY ISSUSPENDED_ TINYINT(1);
ALTER TABLE JBPM_TASK MODIFY ISBLOCKING_ TINYINT(1);
ALTER TABLE JBPM_TASK MODIFY ISSIGNALLING_ TINYINT(1);
ALTER TABLE JBPM_TASKINSTANCE MODIFY ISCANCELLED_ TINYINT(1);
ALTER TABLE JBPM_TASKINSTANCE MODIFY ISSUSPENDED_ TINYINT(1);
ALTER TABLE JBPM_TASKINSTANCE MODIFY ISOPEN_ TINYINT(1);
ALTER TABLE JBPM_TASKINSTANCE MODIFY ISSIGNALLING_ TINYINT(1);
ALTER TABLE JBPM_TASKINSTANCE MODIFY ISBLOCKING_ TINYINT(1);
ALTER TABLE JBPM_TOKEN MODIFY ISABLETOREACTIVATEPARENT_ TINYINT(1);
ALTER TABLE JBPM_TOKEN MODIFY ISTERMINATIONIMPLICIT_ TINYINT(1);
ALTER TABLE JBPM_TOKEN MODIFY ISSUSPENDED_ TINYINT(1);
把上面这些字段改了之后就插入正常了.
附:编程方式部署流程定义文件代码如下:
public class HelloWorldDbTest extends TestCase {
static JbpmConfiguration jbpmConfiguration = null;
static {
// An example configuration file such as this can be found in
// 'src/config.files'. Typically the configuration information is in the
// resource file 'jbpm.cfg.xml', but here we pass in the configuration
// information as an XML string.
// First we create a JbpmConfiguration statically. One JbpmConfiguration
// can be used for all threads in the system, that is why we can safely
// make it static.
jbpmConfiguration = JbpmConfiguration.parseXmlString(
"<jbpm-configuration></jbpm-configuration>" +
// A jbpm-context mechanism separates the jbpm core
// engine from the services that jbpm uses from
// the environment.
" <jbpm-context></jbpm-context>" +
" <service name="persistence" factory="org.jbpm.persistence.db.DbPersistenceServiceFactory"></service>" +
" " +
// Also all the resource files that are used by jbpm are
// referenced from the jbpm.cfg.xml
" <string name="resource.hibernate.cfg.xml" value="hibernate.cfg.xml"></string>" +
" <string name="resource.business.calendar" value="org/jbpm/calendar/jbpm.business.calendar.properties"></string>" +
" <string name="resource.default.modules" value="org/jbpm/graph/def/jbpm.default.modules.properties"></string>" +
" <string name="resource.converter" value="org/jbpm/db/hibernate/jbpm.converter.properties"></string>" +
" <string name="resource.action.types" value="org/jbpm/graph/action/action.types.xml"></string>" +
" <string name="resource.node.types" value="org/jbpm/graph/node/node.types.xml"></string>" +
" <string name="resource.varmapping" value="org/jbpm/context/exe/jbpm.varmapping.xml"></string>" +
""
);
}
public void setUp() {
jbpmConfiguration.createSchema();
}
public void tearDown() {
jbpmConfiguration.dropSchema();
}
public void testSimplePersistence() {
// Between the 3 method calls below, all data is passed via the
// database. Here, in this unit test, these 3 methods are executed
// right after each other because we want to test a complete process
// scenario. But in reality, these methods represent different
// requests to a server.
// Since we start with a clean, empty in-memory database, we have to
// deploy the process first. In reality, this is done once by the
// process developer.
deployProcessDefinition();
// Suppose we want to start a process instance (=process execution)
// when a user submits a form in a web application...
processInstanceIsCreatedWhenUserSubmitsWebappForm();
// Then, later, upon the arrival of an asynchronous message the
// execution must continue.
theProcessInstanceContinuesWhenAnAsyncMessageIsReceived();
}
public void deployProcessDefinition() {
// This test shows a process definition and one execution
// of the process definition. The process definition has
// 3 nodes: an unnamed start-state, a state 's' and an
// end-state named 'end'.
ProcessDefinition processDefinition = ProcessDefinition.parseXmlString(
"<process-definition name="hello world"></process-definition>" +
" <start-state name="start"></start-state>" +
" <transition to="s"></transition>" +
" " +
" <state name="s"></state>" +
" <transition to="end"></transition>" +
" " +
" <end-state name="end"></end-state>" +
""
);
// Lookup the pojo persistence context-builder that is configured above
JbpmContext jbpmContext = jbpmConfiguration.createJbpmContext();
try {
// Deploy the process definition in the database
jbpmContext.deployProcessDefinition(processDefinition);
} finally {
// Tear down the pojo persistence context.
// This includes flush the SQL for inserting the process definition
// to the database.
jbpmContext.close();
}
}
public void processInstanceIsCreatedWhenUserSubmitsWebappForm() {
// The code in this method could be inside a struts-action
// or a JSF managed bean.
// Lookup the pojo persistence context-builder that is configured above
JbpmContext jbpmContext = jbpmConfiguration.createJbpmContext();
try {
GraphSession graphSession = jbpmContext.getGraphSession();
ProcessDefinition processDefinition =
graphSession.findLatestProcessDefinition("hello world");
// With the processDefinition that we retrieved from the database, we
// can create an execution of the process definition just like in the
// hello world example (which was without persistence).
ProcessInstance processInstance =
new ProcessInstance(processDefinition);
Token token = processInstance.getRootToken();
assertEquals("start", token.getNode().getName());
// Let's start the process execution
token.signal();
// Now the process is in the state 's'.
assertEquals("s", token.getNode().getName());
// Now the processInstance is saved in the database. So the
// current state of the execution of the process is stored in the
// database.
jbpmContext.save(processInstance);
// The method below will get the process instance back out
// of the database and resume execution by providing another
// external signal.
} finally {
// Tear down the pojo persistence context.
jbpmContext.close();
}
}
public void theProcessInstanceContinuesWhenAnAsyncMessageIsReceived() {
// The code in this method could be the content of a message driven bean.
// Lookup the pojo persistence context-builder that is configured above
JbpmContext jbpmContext = jbpmConfiguration.createJbpmContext();
try {
GraphSession graphSession = jbpmContext.getGraphSession();
// First, we need to get the process instance back out of the database.
// There are several options to know what process instance we are dealing
// with here. The easiest in this simple test case is just to look for
// the full list of process instances. That should give us only one
// result. So let's look up the process definition.
ProcessDefinition processDefinition =
graphSession.findLatestProcessDefinition("hello world");
// Now, we search for all process instances of this process definition.
List processInstances =
graphSession.findProcessInstances(processDefinition.getId());
// Because we know that in the context of this unit test, there is
// only one execution. In real life, the processInstanceId can be
// extracted from the content of the message that arrived or from
// the user making a choice.
ProcessInstance processInstance =
(ProcessInstance) processInstances.get(0);
// Now we can continue the execution. Note that the processInstance
// delegates signals to the main path of execution (=the root token).
processInstance.signal();
// After this signal, we know the process execution should have
// arrived in the end-state.
assertTrue(processInstance.hasEnded());
// Now we can update the state of the execution in the database
jbpmContext.save(processInstance);
} finally {
// Tear down the pojo persistence context.
jbpmContext.close();
}
}
}
3.2版比3.1版的配置文件多了一个配置项目,加上这个配置项目之后就OK了
<service name="tx" factory="org.jbpm.tx.TxServiceFactory">
因为是按照开发指南的例子写了一个jbpm.cfg.xml,缺少这一条,所以又造成了一个错误。
一般来说,jbpm.cfg.xml其实可以不用写的,jbpm会自动使用org.jbpm包下的default.jbpm.cfg.xml作为配置文件来启动整个jbpm服务。