|
|
Note |
The following documentation can be used as reference documentation for Spring Modules jBPM 3.0.x support as well.
|
jBPM module offers integration between the Spring and jBPM allowing for reuse of Spring's Hibernate support along with the IoC container. The module allows jBPM's underlying Hibernate sessionFactory to be configured through Spring and jBPM actions to access Spring's context.
Users familiar with Spring will see that the jBPM module structure resembles with the orm package from the main Spring distribution. The module offers a central template class for working with jBPM, a callback to access the native JbpmContext and a local factory bean for configuration and creating a jBPM instance.
<beans>
<!-- DataSource definition -->
<bean id="dataSource" class="...">
...
</bean>
<!-- Hibernate SessionFactory definition -->
<bean id="hibernateSessionFactory"
class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
...
</bean>
<!-- helper for reading jBPM process definitions -->
<bean id="simpleWorkflow"
class="org.springmodules.workflow.jbpm31.definition.ProcessDefinitionFactoryBean">
<property name="definitionLocation"
value="classpath:org/springmodules/workflow/jbpm31/simpleWorkflow.xml"/>
</bean>
<!-- jBPM configuration -->
<bean id="jbpmConfiguration"
class="org.springmodules.workflow.jbpm31.LocalJbpmConfigurationFactoryBean">
<property name="sessionFactory" ref="hibernateSessionFactory"/>
<property name="configuration" value="classpath:jbpm.cfg.xml"/>
<property name="processDefinitions">
<list>
<ref local="simpleWorkflow"/>
</list>
</property>
<property name="createSchema" value="true"/>
<property name="processDefinitionsResources">
<list>
<value>classpath:/org/springmodules/workflow/jbpm31/someOtherWorkflow.xml</value>
</list>
</property>
</bean>
<!-- jBPM template -->
<bean id="jbpmTemplate" class="org.springmodules.workflow.jbpm31.JbpmTemplate">
<constructor-arg index="0" ref="jbpmConfiguration"/>
<constructor-arg index="1" ref="simpleWorkflow"/>
</bean>
set
</beans>
The example above shows how (existing) Spring-managed Hibernate SessionFactories and transaction management can be reused with jBPM.
9.2.1. LocalJbpmConfigurationFactoryBean
The main element is LocalJbpmConfigurationFactoryBean which should be familiar to users acustomed to Spring. Based on the jbpm configuration file and the given SessionFactory, it will create a jBPM configuration which can be used for working with the given process definitions. It is possible to replace jBPM xml configuration with jBPM 3.1.x newly added ObjectFactory - note that if both are present the xml configuration is preffered. LocalJbpmConfigurationFactoryBean allows the creation of the underlying schema based on the process definitions loaded automatically at startup.
Note that the sessionFactory property is not mandatory - Hibernate SessionFactory can be reused with jBPM or jBPM can work by itself without any integration with the existing infrastructure. However, in most scenarios, using LocalJbpmConfigurationFactoryBean allows one to take advantage of Spring transaction management infrastructure so it's possible without any code change to use jBPM, Hibernate and jdbc-based code inside the same transactional context, be it managed locally or globally (JTA). Moreover, it is possible to use thread-bound session or OpenSessionInView patterns with jBPM.
LocalJbpmConfigurationFactoryBean is also aware of the enclosing applicationContext lifecycle - jBPM will be initialized once the context is started (usually application startup) and will be closed properly when the context is destroyed (application is shutdown).
Note that LocalJbpmConfigurationFactoryBean can be configured programatically and can be used standalone only to build an jBPM context which can be used independently of Spring Modules jBPM support.
9.2.2. Inversion of Control: JbpmTemplate and JbpmCallback
Another important feature of Spring Modules jBPM support is JbpmTemplate. The template offers very convient ways of working directly with process definitions as well as jBPM API taking care of handling exceptions (be it jBPM or Hibernate based) in respect to the ongoing transaction (if it's present), the underlying Hibernate session (if pesistent services are used) and the jBPM context. jBPM exceptions (and the underlying Hibernate information) are translated into Spring's DAO exception hierarchy. Everything happens in a transparent and consistent manner.This is possible, as with every Spring-style template,even when direct access to the native JbpmContext is desired, through the JbpmCallback:
public ProcessInstance findProcessInstance(final Long processInstanceId) {
return (ProcessInstance) execute(new JbpmCallback() {
public Object doInJbpm(JbpmContext context) {
// do something
...
return context.getGraphSession().loadProcessInstance(processInstanceId.longValue());
}
});
}
As well, as LocalJbpmConfigurationFactoryBean, the JbpmTemplate can be configured programatically and can be used standalone on a pre-existing jbpmContext (configured through LocalJbpmConfigurationFactoryBean or not) and can be used independently of Spring Modules jBPM support.
9.2.3. ProcessDefinitionFactoryBean
ProcessDefinitionFactoryBean is a simple reader that loads jBPM process definition using Spring's ResourceLoaders. Thus, the xml files can be load using the classpath, relative or absolute file path or even from the Servlet Context. See the official documentation for more information.
|
Note |
As reported on the forums, using ProcessDefinitionFactoryBean jBPM 3.1.1will trigger a new process definition to be persisted(through deployProcessDefinition) at each startup. While this is useful in development when the database is created on application startup and destroyed on closing, for cases where the definition doesn't change, the process should not be declared inside Spring XML files.
|
|
Note |
As reported here, due to the static nature of jBPM, process definitions which include sub processes are not loaded properly if a JbpmContext does not exist at the time of the loading (no exception is thrown whatsoever). As a workaround consider using the LocalJbpmConfigurationFactoryBean's processDefinitionsResources property.
|
9.2.4. Outside Spring container
It is important to note that while our example showed LocalJbpmConfigurationFactoryBean and JbpmTemplate template inside a Spring xml, these classes do not depend on each other or on Spring application context. They can be just as well configured programatically and can
9.3. Accessing Spring beans from jBPM actions
Another important feature of Spring Modules jBPM integration is allowing Spring configured beans to be reused inside jBPM actions. This allows one to leverage Spring container capabilities (bean lifecycles, scoping, injection, proxying just to name a few) in a transparent way with jBPM. Consider the following Spring application context:
<beans>
<!-- Spring bean visible inside jBPM processed -->
<bean id="jbpmAction" class="org.MyJbpmActionHandler" singleton="true">
<property name="someProp" ref="anotherBean"/>
...
</bean>
..
</beans>
and jBPM process definition:
<?xml version="1.0" encoding="UTF-8"?>
<process-definition name="simpleWorkflow">
<start-state>
<transition to="myState">
</transition>
</start-state>
<state name="myState">
<transition to="end">
<action name="myAction" config-type="bean"
class="org.springmodules.workflow.jbpm31.JbpmHandlerProxy">
<targetBean>jbpmAction</targetBean>
<factoryKey>jbpmConfiguration</factoryKey>
</action>
</transition>
</state>
<end-state name="end"/>
</process-definition>
JbpmHandlerProxy transparently locates Spring applicationContext and searches the bean identified by the targetBean parameter (in this case jbpmAction) and delegate all calls to the jBPM action. This way, one is not limited only to the injection offered by jBPM container and can integrate and communicate in a very easy manner with other Spring managed beans. Moreover, your action lifecycle can be sigleton (one shared instance) or prototype (every call gets a new instance) or in Spring 2.0 scoped to a certain application component (like one instance per http session).
The optional factoryKey parameter specified in this example should be used when one is dealing with more then one jBPM configuration inside the same classloader (not common in practice). The factoryKey should be the same as the bean name of the LocalJbpmConfigurationFactoryBean to be used (in our case jbpmConfiguration).
在使用了一段时间的jbpm之后,现在因新项目,想把原来没有整合的地方,现在整合一下,这样对于事务能更好的处理。
framewor : springmvc + spring + hibernate + jbpm
目的: HR的签核流程(加班、请假、教育训练等)
对于Ext form只能说看上去很美,对于一个复杂的页面,写惯了html之后,突然让你写一大堆的js,对我来讲确实有点很为难。一时间实在是接受不了。而且对于页面来说不是很直观,比较难控制。
个人意见,对于复杂的页面还是不要用ext了,实在有点繁。
但是对于象登录页面这种,绝对是可以用ext的,简单,而且用户体验又好。
下面的任务就是做一个跟后台交互的登录页面。
一是自己学习,二是网上完整的代码很少。
以便大家交流参考。:)
期待ing
在使用ajax tab的时候,可能有些资料需要返回给当前的页面,这个时候怎么把那个tab的中的页面的资料传到当前页面呢?不懂
tab中嵌入iframe的简单方法
// second tabs built from JS
var tabs2 = new Ext.TabPanel({
renderTo: document.body,
activeTab: 0,
width:600,
height:250,
plain:true,
defaults:{autoScroll: true},
items:[{
title: 'Disabled Tab',
disabled:true,
html: "<iframe src='xxx.jsp' ></iframe>"
}
]
});
这样就可以轻松实现一个嵌入页面。
ajax方式和iframe方式各有特点。
如果只是显示一些内容的话,用ajax方式方便。
如果有操作,那就用iframe,否则页面路径都需要重新设置,而且提交的时候还有些不方便,js好像也有问题。
spring mvc 使用annotation进行controller配置
注:两种urlmapping的模式不能同时使用,如果使用annotation就不能再配置springapp-servlet.xml的urlmapping。
1、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"
xmlns:p="http://www.springframework.org/schema/p"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-2.5.xsd">
<context:component-scan base-package="com.ivo.web.action.spring" />
<bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="viewClass"><value>org.springframework.web.servlet.view.JstlView</value></property>
<property name="prefix"><value>/pages/</value></property>
<property name="suffix"><value>.jsp</value></property>
</bean>
</beans>
<context:component-scan base-package="com.ivo.web.action.spring" />用于指明系统从哪个路径下寻找controller,然后提前初始化这些对象。
2、web.xml
跟一般的mvc配置没有区别。
3、controller配置
具体可以看spring的参考文件,有好几种配置。
3.1 在方法上配置mapping路径
@Controller
public class HelloController {
@RequestMapping("/hello.do")
public ModelAndView processImageUpload() throws IOException {
System.out.println("hello");
return new ModelAndView("org", "jsonString", "test");
}
}
3.2 在class上配置mapping路径,通过参数指定调用的方法
@Controller
@RequestMapping("/hello.do")
public class HelloController {
@RequestMapping(params = "action=save")
public ModelAndView save() throws IOException {
System.out.println("hello");
return new ModelAndView("org", "jsonString", "test");
}
}
方法的返回值可以是null,string 或者ModelAndView,都支持。
以上是系统暂时用到的,其他的以后再研究。
1、Ext.get 获得dom对象,类似于document.getElementById
Ext.get("hideit").on('click', function() {
var w = Ext.getCmp('west-panel');
w.collapsed ? w.expand() : w.collapse();
});
2、Ext.getCmp 获得Ext组件对象,然后就可以直接进行组件操作,首先组件要有ID。
前面在使用了简单的tab之后,在后来的应用中,又用到了高级tab。
需要用户点击一个链接之后,在panel中新增tab。这里有很多地方有疑问。
1、在var viewport = new Ext.Viewport()中定义tab是这样子的。
new Ext.TabPanel({
id:tabs,
region:'center',
enableTabScroll:true,
defaults: {autoScroll:true},
deferredRender:false,
activeTab:0,
items:[{
contentEl:'center2',
title: 'Start',
autoScroll:true
}]
})
但是这样子导致这个TabPanel没有变量名,不能直接操作。
然后我试了通过viewport.add进行添加的方式,可能是方法使用错误,导致没有出来。
如果效果出来了。
后面还有问题,我怎么通过这个tab来显示一个页面呢。通过ajax tab来显示。在basic tab这个例子里有看到过,知识还没有研究。
下面是动态添加tab的方法
function addTab(){
tabs.add({
title: 'New Tab ' + (++index),
iconCls: 'tabs',
html: 'Tab Body ' + (index) + '<br/><br/>'
+ Ext.example.bogusMarkup,
closable:true
}).show();
}
就通过TabPanel这个对象的变量来直接add。在add时候再动态载入页面内容。
var viewport = new Ext.Viewport({
layout: 'border',
items: [{
region: 'north',
html: 'menu'
}, {
id: 'center_panel',
region: 'center',
layout: 'card',
items: [
{id: 'first_center', html: 'first center'}
]
}]
});
var center = Ext.getCmp('center_panel');
center.remove('first_center');
center.add({
id: 'second_center',
html: 'second center'
});
center.getLayout().setActiveItem('second_center');
center.doLayout();
通过指定TabPanel id,然后通过Ext.getCmp('center_panel'),就可以获得这个panel的句柄,就可以对这个组件进行操作。layout在add/remove之后需要调用center.doLayout()方法,才能使后来新建的tab的生效。
3、ajax tab
function addFormTab(strScreen_ID, strScreenName){
var tabs = Ext.getCmp('tabs');
tabs.add({
id: strScreen_ID,
title: strScreenName,
//html: 'second center',
autoLoad: {url: './pages/web/business_frame.jsp', params: 'screen_ID=WEB.BU&screen_FK=' + strScreen_ID},
closable:true
});
tabs.getLayout().setActiveItem(strScreen_ID);
tabs.doLayout();
}
autoLoad: {url: './pages/web/business_frame.jsp', params: 'screen_ID=WEB.BU&screen_FK=' + strScreen_ID}
指定这个autoload,就可以从相应的指定页面载入。
以上已经测试成功。嘿嘿:)
简单tab的应用,参考例子
var tabs = new Ext.TabPanel({
renderTo: 'tabs1',
width:450,
activeTab: 0,
frame:true,
defaults:{autoHeight: true},
items:[
{contentEl:'script', title: 'Short Text'},
{contentEl:'markup', title: 'Long Text'}
]
});
tab的激活事件
在item的配置中增加
listeners: {activate: handleActivate}
handleActivate是一个方法,也就是当激活某一个tab的时候,就会调用这个方法。
// second tabs built from JS
var tabs2 = new Ext.TabPanel({
renderTo: document.body,
activeTab: 0,
width:600,
height:250,
plain:true,
defaults:{autoScroll: true},
items:[{
title: 'Normal Tab',
html: "My content was added during construction."
},{
title: 'Ajax Tab 1',
autoLoad:'ajax1.htm'
},{
title: 'Ajax Tab 2',
autoLoad: {url: 'ajax2.htm', params: 'foo=bar&wtf=1'}
},{
title: 'Event Tab',
listeners: {activate: handleActivate},
html: "I am tab 4's content. I also have an event listener attached."
},{
title: 'Disabled Tab',
disabled:true,
html: "Can't see me cause I'm disabled"
}
]
});
autoLoad:异步载入的页面。
事件的自定义
treeDept.on('click', function(node){
if(node.leaf==true){
addSelected(node.id, node.text);
}
});
如何自定义事件。上面针对tree的单击事件,设置的单击时所要做 的动作。
其他的事件设置可以参考这个。从API上查到相应的事件名称,然后就可以设定了。
|