Tuesday, March 24, 2009

Create Spring beans dynamically

Spring XML declared beans can be wired building your business structure. The problem with this approach is that these beans are loaded on the start up, when the Spring Context is created, which does not leave much of playground to modify or change beans at run time. How ever Spring offers opportunity to load beans in the Spring context on run time when beans are needed, and populate them at need.
For doing this, we need the Spring Application context. For this to accomplish, one can declare one dedicated Spring context bean, which will implement the ApplicationContextAware and BeanFactoryPostProcessor interfaces. This should look something like this:


public class MyContextWrapper implements ApplicationContextAware,
BeanFactoryPostProcessor {

private ApplicationContext appContext;
private ConfigurableListableBeanFactory factory;

public void postProcessBeanFactory(ConfigurableListableBeanFactory factory)
throws BeansException {
this.factory = factory;
}
public void setApplicationContext(ApplicationContext c)
throws BeansException {
this.appContext = c;
}

//setters and getters

}



The postProcessBeanFactory will be executed after reading the configuration files of the spring context. Here one can do other configurations and bean loading, or save the factory for later use.
The Spring application context can be used for later dynamic bean retrieval or other purposes.

For this approach to work, one should let spring load this bean in to it's context by declaring the bean in the XML configuration file as follow:






Now this bean can be loaded in any other bean of the application via referencing it:








Now that we have the grip of the Spring context and it's factory, we can create beans dynamically. For this purpose, we can use the GenericBeanDefinition which allows to load bean definitions as follows:

BeanDefinitionRegistry registry = ((BeanDefinitionRegistry )factory);

GenericBeanDefinition beanDefinition = new GenericBeanDefinition();
beanDefinition.setBeanClass(MyBeanClass.class);
beanDefinition.setLazyInit(false);
beanDefinition.setAbstract(false);
beanDefinition.setAutowireCandidate(true);
beanDefinition.setScope("session");

registry.registerBeanDefinition("dynamicBean",beanDefinition);


As one can see, this bean is created in the session scope and will be stored in the session of the user. The property auto wire candidate tells spring if dependency's of the bean such as setter's or getter's or constructor argument's should be handled automatically by Spring. The property lay init tells Spring if this bean should be instantiated when needed.

To get a handle of Spring bean, one can use the Spring application context as follows:

Object bean=
getApplicationContext().getBean("dynamicBean");
if(bean instanceof MyBeanClass){
MyBeanClass myBean = (MyBeanClass) bean;

// do with the bean what ever you have to do.
}


As you can see, the dynamic bean creation in Spring is no big deal.It is easy to use, an certainly handy in many situations.

Thursday, March 19, 2009

JSR 286 IPC with JSF

In case you are portlets developer, you know what JSR 286 is. It is the holy grail for the portlets which should enable the portlets to communicate with each others. At least you would think it is the holy grail, until you read the specs and look upon the Suns minimalistic examples.
It seems to me, this spec is out for it's own sake, and forwards the developers in the ice age of pure html, which is unthinkable for someone who has got used to API's such as JSF or Struts. Vendors as JBoss or ICEFaces have yet to deliver a bridge which will support JSR 286 with an AJAX push.

The sad news is that JSR 286 works only with out AJAX push, and you have to do some work around to get the grips of it in JSF Portal environment.

The first thing to do is to define the event you want to publish. This is done in the portlet.xml. There are three declaration there:
  1. One Global declaration of your event
  2. Supported publishing event for your pulbishing portlet
  3. Supported processing event for our consumer portlet


The global event declaration looks as follow:



x:EventName
java.lang.String



In the Publishing portlet, put the following:



x:EventName



And atlast, in the consumer portlet:



x:EventName


Now that you have configured your event that it is only a simple String, you should set it. This can be done in two way's:

  1. Either extend javax.portlet.faces.GenericFacesPortlet and override the

    public void processAction(ActionRequest request, ActionResponse);
  2. Or set the event in one of your Faces action methods.
If you prefer the first way, than you have to think that your to pass your full class name in the portlet.xml for portlet instantiation which would look like this:


org.mycomp.IPCPublisher



If you prefer the JSF action method way, than your portlet.xml will look as usual:

javax.portlet.faces.GenericFacesPortlet



In you decide to override the method of the GenericFacesPortlet, than you will set the event similar to this:


public void processAction(ActionRequest request, ActionResponse response)
throws PortletException,IOException {

QName qname = new QName("http://www.mycomp.com/myevent" , "EventName");
response.setEvent(qname, "Hallo IPC Communication.");
}


If you decide you would like to publish this event from inside of your JSF action method, you can do that as follow:

public void publishIPCEvent(ActionEvent event){
Object response = FacesContext.getCurrentInstance()
.getExternalContext()
.getResponse();

if(response instanceof ActionResponse){
ActionResponse aResponse = (ActionResponse)response;
QName qname = new QName("http://www.mycomp.com/myevent" , "EventName");
aResponse.setEvent(qname, "Hallo IPC Communication.");
}
}



This method will be called as usual in JSF:








What is left is to read out this event in the Consumer portlet.
You should extend the Generic Faces Portlet and override the processEvent method. By doing that, don't forget to put the class definition in the portlet.xml as follow:

org.mycomp.IPCConsumer

Override the method as follow:

public void processEvent(EventRequest request, EventResponse response) {
Event event = request.getEvent();
if(event.getName().equals("EventName")){
String ipc = event.getValue();
response.getPortletSession().setAttribute("ipc",ipc);
}
}


As you can see, I read out the event and compare it's name if it is my event I want to handle. Than I read it's value and set it in the portlet session as attribute.

To get this value inside of JSF, you should do something like this:

Object ipc = FacesContext.getCurrentInstance()
.getExternalContext().getSession(false)
.getAttribute("ipc);



Some say that one can annotate the certain method, which should be responsible for processing the event. This should look something like this:

@ProcessEvent(qname="{http://www.mycomp.com/myevent}EventName")
public void myEventProcessingMethod(EventRequest request, EventResponse response){
Event event = request.getEvent();
if(event.getName().equals("EventName")){
String ipc = event.getValue();
response.getPortletSession().setAttribute("ipc",ipc);
}
}



But this method annotation did not work for me inside of JSF. The same should work with java.util.HashMap instead of java.lang.String as well.

Anyways, this IPC approach is not that straightforward as some would like it to be, but it fullfils it's purpose.

Tuesday, March 17, 2009

Create your JSF componenst with out JSP or Facelets Tags

It is personal reference. Some love XML Syntax, some try to save them from the XML Jungle. JSF is a framework that allows you to create components dynamically. The JSF Tags are only option.

If you prefer to create your compnents without JSP or Facelets, and you don't want to envent the weel again, you can define your JSF Panel Grid in your JSP or Facelet as follow:





Define the bean in Spring config file as follow:





This bean holds a instance of the JSF HtmlPanelGrid which renders the JSF Panel Grid for you. The JSF components should be added to the Panel Grid with it's public method getChildren().add(Object o);. Here is the example:


package org.mypackage;

import javax.faces.application.Application;
import javax.faces.component.html.HtmlOutputText;
import javax.faces.component.html.HtmlPanelGrid;
import javax.faces.context.FacesContext;


public class MyBean {

private HtmlPanelGrid panelGrid;

public MyBean(){

}
public void init(){

Application application = FacesContext.getCurrentInstance().getApplication();
setPanelGrid((HtmlPanelGrid) application.createComponent(HtmlPanelGrid.COMPONENT_TYPE));

HtmlOutputText text = (HtmlOutputText) application.createComponent(HtmlOutputText.COMPONENT_TYPE);

text.setValue("Hallo JSF with out Tags.");

getPanelGrid().getChildren().add(text);

}
public void setPanelGrid(HtmlPanelGrid panelGrid) {
this.panelGrid = panelGrid;
}
public HtmlPanelGrid getPanelGrid() {
return panelGrid;
}

}

  1. In line 16 is the public method which will be ivoked by Spring after instantiation of the Bean.
  2. Line 18 gets an instance of the current application.
  3. On line 19 we create an instance of HtmlOutputText with the help of the method createComponent which takes String as argument. Every JSF Component defines public static field COMPONENT_TYPE which returns the type of the component to be created.
  4. On line 21 a instance of HtmlOutputText is created in the same way as the HtmlOutputText.
  5. In line 23 we set the value of the output text.
  6. In line 25 we set the output text component as child of the Panel Grid.
On the end of the day, when JSF try's to render the Panel Grid with the ID dynamic in the JSP or Facelets, the Property panelGrid of the backing bean will be called and our instance would be copied and rendered.

In this way, we can create whole views or parts of it, as if we program in pure Java.

Monday, March 16, 2009

Basic RichFaces Project with Spring

To create basic RichFaces enabled project, you can run the following maven command provided by JBoss.
mvn archetype:generate
-DarchetypeGroupId=org.jboss.portletbridge.archetypes
-DarchetypeArtifactId=richfaces-basic
-DarchetypeVersion=1.0.0.B6
-DgroupId=org.whatever.project
-DartifactId=myprojectname
-DarchetypeRepository=http://repository.jboss.org/maven2/
Make sure that you use the proper version of the Portlet Bridge of Jboss. Read more here
To enable Spring to manage your JSF Beans you should add this context arguments to your web.xml




org.springframework.web.context.ContextLoaderListener





org.springframework.web.context.request.RequestContextListener




This are the listeners which enables Spring to load it's context and create the beans, and to process Request from JSF to Spring and preserve the session.

Inside of faces-config.xml :



org.springframework.web.jsf.DelegatingVariableResolver




This delegates the JSF Variable resolver to look up for EL Expressions defined beans in Spring. In other words, it replaces the standard JSF EL resolver.

Now you would be able to define your JSF Beans in Spring as follows:



xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:osgi="http://www.springframework.org/schema/osgi"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd">







This bean can be used with your JSF Tag as usual:





In deed simple.

Here is the full web.xml:



xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">


javax.faces.STATE_SAVING_METHOD
server




javax.portlet.faces.renderPolicy
ALWAYS_DELEGATE



org.ajax4jsf.RESOURCE_URI_PREFIX
rfRes



org.richfaces.LoadStyleStrategy
NONE



org.richfaces.LoadScriptStrategy
NONE



org.ajax4jsf.COMPRESS_SCRIPT
true



org.richfaces.CONTROL_SKINNING
enable



contextConfigLocation
classpath:spring-context.xml



RichFaces Filter
richfaces
org.ajax4jsf.Filter



richfaces
Faces Servlet
REQUEST
FORWARD
INCLUDE



com.sun.faces.config.ConfigureListener



org.springframework.web.context.ContextLoaderListener



org.springframework.web.context.request.RequestContextListener





Faces Servlet
javax.faces.webapp.FacesServlet
1




Faces Servlet
/faces/*


Faces Servlet
*.jsf



FacesServlet
*.mk




10



Restrict access to JSP pages

Restrict access to JSP pages



With no roles defined, no access granted



BASIC




Sunday, March 15, 2009

Adding Spring to the project

Spring is generally highly rated for it's IoC capabilities. It gained it's popularity while developers had hard times with EJB 2.0 Specs.

Since Spring can be needed in more sub-project or modules, it is only reasonable to create a central place in your project to implement your Spring code. Create a Maven module as described in the revious post. It should look similar to this:


The Spring configuration files should be placed inside of the src/main/resources folder.

The main Spring configuration file is named applicationContext.xml by default. How ever this is not mandatory. You can name it hwat ever you like. I called it spring-context.xml.

If you are using the Sprng for web app or portlets, you can tell Spring where to find your custom configuration file with the following entry in your web.xml descriptor:


Now that you have the basic structure for your Spring, you should add the Module in to the main Project pom.xml :


and add it as dependency to be available in other projects:
Now that the Spring module is configured and available as dependency for other modules, you can bind it in other modules by adding the dependency in their pom.xml as follows:

As you can notice, the dependency in other modules pom.xml is added without the version tag. In this way, the versioning of the project dependency's is handled central in the main project pom.xml.

Saturday, March 14, 2009

Maven project architecture

Maven alows the developer to manage Enterprise projects in a modular way. This keep the project in order when it grows in time.

To create new Maven project, you can click File>New Project and select Maven Project



By selecting Next the following dialog will show up:



Click finish. What is important to note is the packaging of the project. It is set on POM.

Next, in the workspace will show the new project. You can than create new Folder and name it modules and underneath this folder you can create other folders that will include your modules or component projects. Your project should look similar to the following:


Clicking the pom.xml should produce the following code:


To create new Module Project, you should click File > New Project and select Maven Module


If your main project was not authomatically selected as parent Project, you should click Browse and select it from the work space. Click Next.


Click finish. The Project will appear in your work space and looks like this:


Close the project, and remove it from the work space. But make sure you don't delete it. Go on your hard disk, where your wrk space is, and copy the new created project in the folder of your main project. After this, it should look something like this:




All we have to do, is to tell maven where to find the new Module. If you open the main project pom.xml, you will notice that Eclipse added your module as follows:


Change the entry in to tag as follows:


The last but not the least is to add the module as a dependency in the main project, so that other sub project- modules can import it as dependency.


In your command console, navigate to the folder of your main project and execute the following maven command:
mvn -X clean install

If everything goes well, maven will end with the following message: