A working sample with JBoss Portal – Spring Webflow – Primefaces

Introduction

You would find in this blog a feasibility study project (available under github) about making JBoss Portal, Spring Webflow and Primefaces to work together.

Naturally I will tell my reasons to produce this project and along the way you will experience the adventures that was necessary to realize it. I will also provide informations about how to get the project from github, build it and deploy it in JBoss Portal, so you can use it for your researches or may be use it in production.

  • Motivations
  • Solutions
  • Project Structure
  • Challenges
  • Project build process and deployment
  • Final thoughts
  • Conclusion

Motivations: The idea for writing this blog come out with our struggle in one project with JBoss Portal.

Our team was full of people with extensive J2EE web development experience but pratically no Portal development. Like every other good programmer,  :),  we were for using the proven frameworks like Spring, JSF, CXF, etc…

One inevitable fact that we have to deal in the days of Web 2.0,  was the existence of lots of Ajax functionality (under the hype of Ajax, Business Side of the project had decided that under normal circumstance, the functionality that should belong 10 web pages in a forms based web application, should be presented under 2 web pages….).

This produced the necessity turn on and off the JSF components in these 2 web pages with Ajax, made some things in the application much bigger challenge. Well the natural way to proceed in this situation, is to look first what was JBoss presenting as solution.

That was the times when JBoss bought the Exadel and working hard to develop their JSF Portlet Bridge and Ajax functionalities on top of the Richfaces. While we didn’t have too much experience with Ajax – JSF combination in Portal world, so we decided to trust JBoss and follow their technology stack…with some initial pain actually the results were Ok but then we started to feel hidden problems presented with previously mentioned challenging Ajax requirements…..

Our project was dependant from several other partner systems and some of them were not filling the performance requirements of a modern web applications, because of this particular situation, they were designed asynchronously. So when we need information from one partner systems, we should first send the request and we would get a technical confirmation that request succesfully received then the partner system would call us the with the real results when they are ready.

Direct consequence of this scenario is that the GUI would render some wait messages and wait until the asynchronous response is there, with Ajax push functionalities (Comet) , would render the delivered results….. Now think about the following scenario, we have nearly 30 partner systems and 15 of them creating all the time events. If you can see what sort of a problems this can cause, let me summarize quickly.

Our application developed with primitive web application concepts, so the decision of a JSF component should be rendered or not, occurs inside of the render methods of the components. For an application, that has one web page and only one form, that might not be too big of a problem but our page our overloaded with the functionality of 10 forms and the JSF components that are inside of these, are turning on and off themselves completely dependant on these asynchronous events….

Well the things started getting out of hand quickly, everything that we developed looked good in development and test environments, but when the software deployed to production environment, events are coming totally different order and speed, then the production environment. Nothing that we developed and accepted from the QS department are looking the same in production environment, while we got the Ok from QS during the development phase, lots of the problems are discerned during the production phase and lots of code is already produced so we were inside of a trap….

On top of that, we were having massive problems with basic frameworks because they were not designed to function under the Portal environment, biggest headache was the dependency injection functionality of the Spring…. The scope Session was not functioning correctly inside of Portal Framework (in the sense of J2EE web application). In Portal environment, Session Scope resolves to portlet session scope which is only accessible from one portlet, so that several different portlets can not see the same object under the session. While in our application, there were several portlets which are trying to share same model objects, to present a consistent view of the system and that is proved to be a big challenge. Naturally Spring has a solution for the mentioned scope problem, we should use a Spring aware Portlet (DispatcherPortlet).

Unfortunately our decision to go with JBoss Portlet Bridge limited our possiblities here also. JBoss Porlet Bridge and Richfaces requires that any JSF based application should use their Portlet implementation, which is doing lots of initialisation for Richfaces Ajax framework….

Solutions: For the above mentioned problems, the solutions were existing, the only problem was to convince them play together….

Many of you certainly know that, Spring Web Flow is the way to go in such a form based application (wizard type lets say) that everything happens as a reaction to events passed to the system.

Spring Flow is a basic State Machine (a little bit lightweigth version of State Machine theory) it is a good design for the requirements of most web applications with lots of useful functionality. It has some weak spots with Ajax that I will mention later but it was a good start-up to bring the discipline necessary to our application.

Unfortunately any attempt to integrate Spring Web Flow to Portal environment has to overcome some of the hurdles that I mentioned previously, mainly making a JSF framework (with Ajax capabilities) to work with Dispatcher Portlet in JBoss Portal (I know that there are some samples with Life Array without Ajax functionality but the reason that I concentrate for JBoss, was that most of J2EE web application developers had used the JBoss Application in some point in their past and it is useful to have the services provided with JBoss).

My first try to integrate the DispatcherPortlet and the RichFaces failed monumentally, JBoss Portlet Bridge was doing too much work for the initialisation of the Richfaces, my tries to imitate the functionality was doomed to fail while the functionality was dispersed to the several layers and it was nearly impossible to figure out without knowing the internals of the RichFaces and only with reading their code.

I was about the give up but then some friend of mine, make me aware of the Primefaces and I was intrigued by its simplicity and I start looking deeper (mainly the way Primefaces handle the Ajax that it delegates main Ajax functionality to jQuery and some other proven libraries and with only one JSF Phase Listener provide the necessary functionality for Ajax).

From now on you will read my adventures about integrating JBoss Portal, Spring Web Flow and Primefaces…. First of all, I have to talk about my proof of concept test application.

I am a person that can think and understand much better with samples and I believe it is same for most of the developers out there. So I would like to have a sample application that people can look how the things are running, look into it and copy the parts of it, if it is useful to them….

My other motivation, is to provide a code bases to discuss, if some problems comes up….. It is a maven project in github and if everything works correctly it shouldn’t be too big of a problem to get it up and running….

Basically this project represent requirements our actual production project, we have a text field that we can enter random text which we can add into a list or reverse it, then add it to the list. To simulate the asynchronous functionality, we have a function that takes the texts inside of the lists and count how many words exists in the texts in a separate thread, then waits for 2 seconds and send results to the Web GUI with Ajax Push (Comet)(GUI renders first a wait status to signal a long running operation is in progress and with the event it re-render itself with the actual results) Here is screen shot from the simple GUI….

A screenshot from proof of concept project

Project Structure:

Before I go some detail what were the challenges that I had experienced during the implementation of the technology demo, I like to show the demo project structure so you would not feel lost when I go to the details. The project is built with maven, so project structure is accordingly a nested maven project and it looks like this.

Project structure

As you may see there is one jbp_swf_primefaces main maven project and the other nested projects…the names are giving a good idea about the content I guess, in next part, challenges, you would get a pretty good idea why they are needed.

Challenges:

First challenge was naturally to convince DispatcherPortlet to work with a JSF framework inside of the JBoss Portal.

Developers of the Spring has an interesting idea to simulate the Portal lifecycle phases, as you may know Portlet has two phases called Action and Render phase. Normally any request parameters from the action phase (action parameters should not go to the render phase) should not be transfered to the Render phase. To guarantee this, when the DispatcherPortlet receives a HTTP POST from JSF framework (JSF Form Submit) it goes over the lifecycle of the JSF framework and makes necessary changes to the model (inside of the doActionService).

At the end this process, DispatcherPortlet redirects the response to the client with an 302 Http Status code so the browser will issue a HTPP GET requests then the parameters from the action phase are eleminated (that has also nice side effect while it prevents the re-submit of the page with refresh or back button). This nice feature has one consequences for our purposes, Primefaces uses some POST parameters to tell the JSF framework which partial updates the response should contain and while the GET request doesn’t contain any parameters this information is now lost.

To prevent this I subclassed the DispatcherPorlet with the class SwfPrimefacesDispatcherPortlet (which you can find in dispatcher-portlet in github project) and override the method doActionService so at the end it can copy the parameters that are relevant for the Primefaces (if you have to modify this method, you must pay attention not pass every parameter to the GET request that would cause double submissions).

One other point, at least in Firefox the browser has a tendency to cache the GET requests. To prevent this, I also added a request parameter that create random request parameters.

I have a small request here, if anybody knows in which class this 302 redirect is triggered in Spring-Portlet, please let me know, I could find out that.

Second challenge was, even that Spring Web Flow examples for portal were working with the JSF reference implementation (and that is not good enough if you need Ajax functionality) , Richfaces (while it is too dependant on JBoss Portlet Bridge) and Primefaces implementations were not working.

For some reason, jsf-portletbridge from Sun is not working with JBoss Portal, so I have to change somethings (funnily JBoss Portal was handling the response streams differently then Life Array because the sample application from the Spring Webflow seems to be working under Life Array) . So below you can find this story…

First thing you have to know, JSF Reference Implementation, JSF Portlet Bridge and Spring Web Flow contains all ViewHandlers and for all these technologies to work correctly under the portal, the classloader has to load them in a certain order.

Unfortunately, I could not find anything in the JSF specification to wire all these handlers in a configuration to dictate the loading order. So for JBoss, it seems that only factor affecting in which order ViewHandlers initialized,  dependends on which order classloader loads the jars, in JBoss which happens to be  alphabetical….

So you would see some funny maven artifact names in this blog, the reason is that I am trying to force JBoss to load the artifact in some certain order. That brings us to the artifact called mridge (actually bridge but that has to load after the JSF implementation ViewHandler so mridge). The other option to build a hard coded ViewHandler chain but that is an idea that I am too not impressed with it….

In mridge project,  you will see that I have to implement my own version of a ViewHandler, JBPViewHandler.  Main motivation behind it, somehow JBoss Portal handles streams differently then the way jsf-portletbridge implementation of the Sun expects. For this reason, we are using a nullViewHandler, so when JSF framework tries to close/flush/etc… a stream, that has no effect to the real portal response and make necessary replace operation of the writers depending on what happens in JSF framework.

This ViewHanlder also has to provide a ViewRoot for the JSF framework to support namespace issues that you would see in the next paragraph. Another functionality you would see in this project is an implementations of ExternalContext, one for Action phase portlet lifecycle, one for Render phase of the portlet lifecycle and a Factory to be able to configure that. Why we need that, well a Portlet can be included in a Page in the portal multiple times and portal framework (at least JBoss Portal) has an unique namespace for every inclusion of portlet (also a ViewRoot for the same purpose), so there would be no name collision for the JSF components. Somehow original implementation of the Primefaces can not handle that out of the box and requires some support from PortletBridge (actually there would be some other changes in Primefaces but we would come to that later).

So the functionality to read the namespace exist only render phase of the portlet life cycle, so we have to get this value during the render phase and pass it to the action phase (while initial render phase happens first for every portlet before action phase) . We would get the value at the ExternalContext build for render phase (At the moment I am using session to pass this information to the action phase, actually I am not too happy about it, if you have a better idea please let me know). At the other side, ExternalContext that build for action phase will take this value and pass to the JSF framework. The factory object look to see which portlet phase we are in, pass the according instance to JSF  framework, naturally we have to configure this ContextFactory inside of the faces-config in the mridge project.

Third challenge was related to the Primefaces, after the mentioned changes, Primefaces and Spring Web Flow functioned correctly but only for web 1.0 requests and not for Ajax requests. After some research, I figured it out that the problem appears to be Primefaces Ajax framework (jQuery btw) making the submits to Portal page.

Now what I just wrote might seem weird but here is the problem. When jQuery makes an Ajax request it is expecting a partial response but because the request submitted to the Portal page, the  response is the whole Portal page and not partial response, jQuery was not able parse this response.

JSF frameworks like Richfaces has a different approach, they are communicating directly web application that is lying behind the Portal framework. Primefaces, out of the box doesn’t have such a functionality. So it seems to be there is two potential solutions to the problem. First a filter that would alter the response coming from the Portal framework and extract partial response from it and send it to the jQuery at client side.

I tested this and it works, you can find the necessary artifact in the maven project portal-filter. If you build the project with maven profile server_side (mvn clean install -Pserver_side), deployment artifacts that would be produced, provides this functionality.

The problem with this, I was not quite happy with the solution and I was not sure it will work in production environment effectively and efficiently (creating two response streams and probable memory effects, etc….). Other possibility, is to do this modification at client side (extracting the partial reponse from the whole portal page response) with minimum consequences at client side, so I modified the jQuery implementation so that it would not throw an error when it gots the whole portal page as response from the server and try to extract partial response with javascript and update the page with jQuery. This way there would be no extra load at server side and it seems to be working good also. You can find the this version of the jQuery under the directory, \primefaces-patch\patch-primefaces\src\main\resources\META-INF\resources\jquery\jquery.js it httpData function which get the following lines

if (ct.indexOf("text") >=0 ) { data = xhr.responseText; if(data.indexOf("") >= 0) { data = data.substring(data.indexOf(""), data.indexOf("") + "".length); //http://groups.google.com/group/jquery-en/browse_frm/thread/95718c9aab2c7483/af37adcb54b816c3?lnk=gst&q=parsexml#af37adcb54b816c3 data = parseXML(data); } }

If any one has a better solution please let me know……

Fourth challenge was to insert inside the modified jquery in primefaces and also some minor fixes in the PrimeFacesPhaseListener class while the version inside of the primefaces 1.1 is not programmed Portal in mind, it was expecting a Servlet request/response and has problems with Portlet request/response. You can find these changes inside of the patch-primefaces maven project, you will also discern that a maven assembly project exist there to create the artifacts that contains the patches for primefaces. The technology demo project would also reference this project as a maven dependency instead of original primefaces dependencies.

Fifth challenge was actually some inconsistent behaviour in the system, the following line in the PrimeFacesPhaseListener.getIdsToUpdate was throwing NullpointerExceptions…

List dynamicUpdateIds = requestContext.getPartialUpdateTargets();

requestContext actually must be initialized from PostRestoreViewHandler class but for some reason that I can actually still not understand totally, was not invoked from the Spring Web Flow. Sometimes it worked, sometimes not. When I try to debug the system it always worked, most of the time this is a hint that there is some thread problem and a race condition occurring somewhere but I was not able figure out the reason. Only thing I can say, when FlowActionListener.processAction method called in Spring Web Flow and this part of the method is executed

context.renderResponse();

the mechanism forcing PostRestoreViewHandler to run is here turned off. The call to the mentioned method places the ‘flowRenderResponse’ flag to the FalshScope and that later read in JsfViewFactory.getView method with the following functionality

if (!facesContext.getRenderResponse()) { JsfUtils.notifyAfterListeners(PhaseId.RESTORE_VIEW, lifecycle, facesContext); }

and then after notifyers are not called….. If you read the comments in the method FlowActionListener.processAction about context.renderResponse()…. “tells JSF lifecycle that rendering should now happen and any subsequent phases should be skipped required in the case of this action listener firing immediately (immediate=true) before validation” This functionality is planned when JSF element that is controlling the submit has it property immediate set, that validation phase of the JSF life cycle must be bypassed .  Actual code was not checking the existence of immediate property but disables the notifiers so I have to modify the code to the following, then it started working correctly. I can still not say what was the real problem but at least I am not getting the NullPointerException anymore

if (source.isImmediate()) { context.renderResponse(); }

I didn’t have this problem when I was debugging, this is an indication of a thread problem but with the solution I can’t see a thread relevance… Anyway, if anybody from Spring Web Flow development team reads this blog and want to look what is going wrong, they have to change the patched FlowActionListener class in the patch-webflow-faces project and deploy, that would reproduce the problem…..

Sixth and final challenge was little bit in fun nature, as I wrote at the beginning, our project was dependant from so many other partner systems and their performances, we have to built some asynchronous structures. To simulate this in the tech_demo project, I build it a service that make a word count over the sentences that are entered to the list in another thread and wait 2 seconds to deliver results to the GUI layer.

Most of you probably heard in Ajax and Web 2.0 world the term Comet, Primefaces has a feasibility study version of it (from many points they are accepting this and promising more production ready version of it in the feature, for more details you can look the their user manual “http://primefaces.googlecode.com/files/primefaces_users_guide_260710.pdf” Chapter 6). With existing the implementation of Comet functionality in Primefaces, events to the Comet can only be triggered from the thread that is rendering the JSF components. So that was not compatible with the scenario that I explained before.  So I have to modify somethings in Comet mechanism in primefaces (which based Atmospehere implementation).

I found some good ideas in a thread in primefaces forum (“http://primefaces.prime.com.tr/forum/viewtopic.php?f=3&t=1480”) and adapted to my needs. The idea is basically to create another version of AtmosphereServlet that places Comet broadcaster in a container that we can access outside of the JSF render thread. One thing I have to change while I have to access to http request and I can’t do that from a background thread, I created a service locator that would get instance of the broadcaster that can retrieve the instance from the background thread. So a call like this would be possible from the background thread…

broadcaster.broadcast(“sentences are refreshed”);

You can find the CometServletLocator and CometServlet in Comet maven project.

Here I also modified JBoss/Tomcat Connector for port 8080 for the Nio Protocol implementation, because it is mentioned so in Atmosphere documentation. We should do the following change in server.xml in the deploy/jboss-web.deployer and it looks like this.

<Connector port="8080" address="${jboss.bind.address}"             maxThreads="250" maxHttpHeaderSize="8192"         emptySessionPath="true" protocol="org.apache.coyote.http11.Http11NioProtocol"         enableLookups="false" redirectPort="8443" acceptCount="100"         connectionTimeout="20000" disableUploadTimeout="true" />

Project build process and deployment:

As I previously mentioned project source code is under github.com, I want to give here some pointers so people get the project from the github.com, build and deploy in JBoss Portal. Personally, I am working at windows at the moment, my best advice is to install the cygwin to get the Git functioanality.

Cygwin is an Unix emulation for windows (you get an unix shell and you can execute unix commands). There are some other Git tools but Git and Maven works perfect with Cygwin.

You can get the Cygwin from the following URL.

Cygwin

During the installation of the Cygwin, it is critical to install the git packages, if you are not familiar with the cygwin, the setup screen should look like this…..

Cygwin git setup

Now we are at the part that we have to get the project from the github. If you are not experienced with github, github itself has a really good help page and tutorials under the following url.

Git Help

The command that we have to execute in cygwin to get the project from github readonly (that only means you can’t commit your changes to my repository) looks like following. Please first go to the directory that you would like to get the project in and from this directory execute the following command.

git clone git://github.com/mehmetsalgar/jbp_swf_primefaces.git

This should create the project structure in the directory…

Now we need Maven to build the project, if you don’t have the maven in your machine you can get it from the following url (I prefer Maven 2.2.1 Maven 3.0 is little bit picky at the moment)…

Maven download Url

If you call the following command at the directory that you downloaded the git repository that should build the project.

mvn clean install -Pclient_side

if the end result looks like this that means it worked….


[INFO]
[INFO] ------------------------------------------------------------------------
[INFO] Reactor Summary:
[INFO] ------------------------------------------------------------------------
[INFO] JBoss Portal - Spring Web Flow - Primefaces - Technology Demo SUCCESS [4.844s]
[INFO] JBoss Portal - Spring Web Flow - Primefaces - Dispatcher Portlet SUCCESS [3.203s]
[INFO] JBoss Portal - Spring Web Flow - Primefaces - Portlet Bridge SUCCESS [1.593s]
[INFO] JBoss Portal - Spring Web Flow - Primefaces - Portlet Filter SUCCESS [1.016s]
[INFO] JBoss Portal - Spring Web Flow - Primefaces - Primefaces Patch SUCCESS [0.031s]
[INFO] JBoss Portal - Spring Web Flow - Primefaces - Patch Primefaces SUCCESS [1.344s]
[INFO] JBoss Portal - Spring Web Flow - Primefaces - Patch Primefaces Assembly SUCCESS [3.516s]
[INFO] JBoss Portal - Spring Web Flow - Primefaces - Spring Webflow Patch SUCCESS [0.015s]
[INFO] JBoss Portal - Spring Web Flow - Primefaces - Patch Webflow Faces SUCCESS [2.078s]
[INFO] JBoss Portal - Spring Web Flow - Primefaces - Patch Webflow Faces Assembly SUCCESS [0.610s]
[INFO] JBoss Portal - Spring Web Flow - Primefaces - Comet ... SUCCESS [1.203s]
[INFO] JBoss Portal - Spring Web Flow - Primefaces - Technology Demo Portlet SUCCESS [7.578s]
[INFO] JBoss Portal - Spring Web Flow - Primefaces - Package . SUCCESS [6.391s]
[INFO] ------------------------------------------------------------------------
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESSFUL
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 34 seconds
[INFO] Finished at: Sat Nov 27 17:09:33 CET 2010
[INFO] Final Memory: 40M/63M
[INFO] ------------------------------------------------------------------------

I also strongly advice to execute the following statement, that would download the source code of the all frameworks that the project references so when later on, we debug the things inside of the Eclipse IDE, we can see the source codes of these framework (Spring Workflow, etc….)

maven dependancy:sources

The maven build also prepares the necessary artifacts for deploying project to the JBoss Portal. The project package is a maven assembly project, it is grouping the necessary artifacts  for the server layout. Which artifacts are going to be prepared is dependent on which maven profile we are building the project.

The client_side profile is responsible to make necessary changes to jQuery-. It would be patched so that the browser can take the partial responses out of the portal response.

The server_side profile is responsible for configuring the filter at the server side so that partial responses are extracted at the server side  and transfered directly to the client browser.

After the build is complete, we should see under package project target directory the following artifact, package-1.0-SNAPSHOT.dir, which is also a directory and now contains the server layout for the deployment.

You can drag&drop (or copy manually)  all the files under the package-1.0-SNAPSHOT.dir to the server/default  directory of JBoss Portal 2.6.4.

This bring us to the server that we are going to use for this test application In my production project, we were dependent to the JBoss Portal 2.6.4, so the instructions here are valid for JSR168/Portlet Spec 1.0 and JBoss 4.2.2 based JBoss Application server. If I would have time in the future, I will try this solution with a JSR 268 / Portlet 2.0 spec container (JBoss Portal 2.7 or GateIn) and probably update this blog.

You can get the bundled version of the JBoss Portal 2.6.4 from the following URL.

JBoss Portal 2.6.4 Bundled

Now we can make some adjustments to the JBoss startup script that would make our life easier. The changes are necessary to be able to debug the project with eclipse and also because some memory requirements for hot deployment.

Please add the following lines to the run.bat file (or shell depending on which environment you are running the JBoss – please remember the the following snippet would look different in the unix derivates) which lies under the bin directory at JBoss Portal installation directory.

set JAVA_OPTS=%JAVA_OPTS% -Xms512m -Xmx1024m -XX:+CMSPermGenSweepingEnabled -XX:MaxPermSize=256m -Dsun.rmi.dgc.client.gcInterval=3600000

Before we start the application I can give you some pointers how to prepare eclipse also in the case you have no maven / eclipse experience.

Please install the m2eclipse plugin to the eclipse from the following URL (Instruction can be found there also).

M2Eclipse installation URL

M2Eclipse will find over maven pom’s, the necessary dependencies for the projects, which is critical for debugging. As you remember we downloaded sources of all the dependencies known to the project . I can tell you that when you are searching a problem in an existing framework, it is extremely valuable to have this functionality.

Now it seems, all the preparation steps are complete, we can start with real testing, please go to the bin directory of the JBoss Portal and call run.bat. The server would be up and running when  you see the following output in the console.

18:04:34,690 INFO [Http11NioProtocol] Starting Coyote HTTP/1.1 on http-127.0.0.1-8080
18:04:34,721 INFO [AjpProtocol] Starting Coyote AJP/1.3 on ajp-127.0.0.1-8009
18:04:34,737 INFO [Server] JBoss (MX MicroKernel) [4.2.2.GA (build: SVNTag=JBoss_4_2_2_GA date=200710221139)] Started in 1m:5s:936ms

You may see some warnings and errors because of the Nio Connector implementation (they are coming from the WSRP module) but it is not critical…..

Now we are ready to call the application for the first time. Please use the following URL to see the default JBoss Portal page.

http://localhost:8080/portal

In this page you would see several tabs and one of them would be our TechDemo application, when we click the tab, we would navigate to our actual application.

A screenshot from proof of concept project

Which looks like as above, in the text entry field, I once entered the text ‘test’ and add it to the list, then I entered the text ‘test demo’, reversed and add it to the list and finally I call the word count which is asynchronously made a word count and refresh the GUI with Comet.

Final thoughts:

Now that we saw the contents of the project, how to build and deploy it, I want explain quickly what I had done with the Spring Web Flow, which was the actually start point of everything.

I like to show you configuration file of the Spring Web Flow and discuss what is happening there.

<?xml version="1.0" encoding="UTF-8"?>

<flow xmlns="http://www.springframework.org/schema/webflow" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/webflow        http://www.springframework.org/schema/webflow/spring-webflow-2.0.xsd">

<view-state id="techDemo-portlet">
<on-render>
<evaluate expression="textEntryRVC.setConsumer(textManagedBean)" />
<evaluate expression="textListRVC.setConsumer(textManagedBean)" />
<evaluate expression="textListResultRVC.setConsumer(wordCountManagedBean)" />
</on-render>
<transition on="add">
<evaluate expression="textManagedBean.addToSentences(textEntryRVC.textEntered)" />          <evaluate expression="textEntryRVC.setTextEntered(null)" />
</transition>

<transition on="reverse">
<evaluate expression="textManagedBean.reverse(textEntryRVC)" />
</transition>
<transition on="wordCount">
<evaluate expression="wordCountController.executeWordCount(textManagedBean.sentences,          wordCountManagedBean)" />
<evaluate expression="wordCountManagedBean.setWordCountRunning(true)"/>
</transition>
<transition on="refresh" >
<evaluate expression="wordCountManagedBean.setWordCountRunning(false)"/>
</transition>
</view-state>
</flow>

Our system is event based and it needs some discipline to handle these events. Spring Web Flow is exactly the right technology to bring this discipline. If you look to the above configuration file, you would see that main element in the configuration is the view state. It defines the state of gui when a certain view is rendered (in this case it is techDemo-Portlet as you may see from the techDemo-portlet.xhtml in the project).

When the GUI gets events in this states, it knows exactly what to do with them with the help of the transition elements, for ex, when ‘add’ event comes, it calls the managed bean to add this to the list, when ‘reverse’ event comes it calls the managed bean to reverse the string and finally ‘wordcount’ event arrive, it calls the the WordCountController to to count the sentences.

Now what you have to pay attention here, if you take the same xhtml and place it under another portlet (or include the fragments of xhtml to another portlet) you would get the same events but you can do completely different things with these events. There would be another view state and the transitions can have a completely another meaning, for ex when you get the ‘add’ event this time it only makes 1 + 1 instead of adding to List, that brings some concept of re-usability also.

That is the power of the Spring Web Flow and statemachine, an event under different contexts can have totally different meanings and we don’t have cover 1000 possible scenarios inside of our render methods. State machine tells us exactly under which state (and context)  we are and we can handle the events accordingly.

Spring Web Flow has some weaknesses, mainly it is build for the Web 1.0 concept and Ajax world is not too much taken into count. It is expected that we receive events and navigate to the other pages/views but that is not the way it happens with Ajax. With Ajax we are also submitting to the same page and stay at same page. That is the reason you are seeing transition elements with no ‘to ‘ attributes because we are not navigating to another page/view state. Naturally when we have lots of Ajax functionality, Spring Web Flow reaches also to its borders but anyway it is a good starting point…..

In a further blog, I would also try explain how can we add from UML generated state machines under the Spring Flow to gain a much bigger control over our business logic.

Conclusion:

Well I hope, you like what you read, I know it became little bit too long, so I hope you were able to stay with me. This my first time trying to write a blog, so if you have any advices the things that I can make better, please let me know, I am really interested to hear.

I hope what you read would be useful somewhere in your professional life……

PS. English is not my native language, I try to do my best but I am sure there are still some mistakes in it and I apologize for it.

About these ads
This entry was posted in Ajax, Atmosphere, Comet, Cygwin, JBoss Portal, JSR168, JSR301, Maven, Portlet, Primefaces, Software Development, Spring Web Flow and tagged , , , , , , , , , . Bookmark the permalink.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s