|
![[Note]](file:///E:/IVO/Library/spring-modules-0.8/docs/reference/html_single/images/admons/note.png) |
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]](file:///E:/IVO/Library/spring-modules-0.8/docs/reference/html_single/images/admons/note.png) |
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]](file:///E:/IVO/Library/spring-modules-0.8/docs/reference/html_single/images/admons/note.png) |
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上查到相應的事件名稱,然后就可以設定了。
|