Sunday, March 27, 2011

Exposing LifeRay Through JBoss EJB3 MDB

We recently did a POC on exposing some Liferay functionality through an MDB in JBoss. Liferay provides a rich web service API available via the portal-web.war. It appears that Liferay did provide native JMS support in the past but has removed this support as of 6.0.

For our purpose we wanted to provide a more fault tolerant solution than web services alone and so looked to expose this functionality via JMS and employ JMS bridging (part of JBoss JMS) to move the messages from disparate applications to the Liferay instance for processing.

Luckily Liferay also provides a rich set of static instance utility classes and to gain access to these we can tear a page from the portal-web.war. Within portal-web.war Liferay exposes a RemotingServlet within the WEB-INF/web.xml and a corresponding WEB-INF/remoting-servlet.xml which then uses Spring provided proxies for the WS interfaces.

In our case we can slim down the remoting-servlet.xml considerably as we are looking to allow our MDB access to Liferay not to extend or change any of the functionality.

To accomplish this we create a war that provides a hook int liferay with a web.xml like this:


<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.4" xmlns="http://java.sun.com/xml/ns/j2ee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
    <!-- Provides access to locally deployed LifeRay -->

    <servlet>
        <servlet-name>Spring Servlet</servlet-name>
        <servlet-class>com.liferay.portal.kernel.servlet.PortalClassLoaderServlet</servlet-class>
        <init-param>

            <param-name>servlet-class</param-name>
            <param-value>com.liferay.portal.spring.servlet.RemotingServlet</param-value>
        </init-param>
        <load-on-startup>0</load-on-startup>
    </servlet>


    <session-config>
        <session-timeout>1</session-timeout>
    </session-config>
</web-app>


And a remoting-servlet.xml such as this:


<?xml version="1.0"?>

<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:jee="http://www.springframework.org/schema/jee"
       xmlns:context="http://www.springframework.org/schema/context" xmlns:tx="http://www.springframework.org/schema/tx"
       xsi:schemaLocation=
               "http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
                http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-2.5.xsd
                http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsd">




</beans>

Once that is complete the next step is to create an MDB. In our case we create this as an EJB jar


@MessageDriven(name = "UserConsumerBean", activationConfig = {
        @ActivationConfigProperty(propertyName = "destinationType", propertyValue = "javax.jms.Queue"),
        @ActivationConfigProperty(propertyName = "destination", propertyValue = "queue/LR_USER_QUEUE")

})

@TransactionAttribute(TransactionAttributeType.NOT_SUPPORTED)
public class UserConsumer implements MessageListener {
    private static final Log LOG = LogFactory.getLog(UserConsumer.class);

    @Resource
    private MessageDrivenContext context;


    protected void setContext(MessageDrivenContext context) {
        this.context = context;
    }

    public void onMessage(Message message) {
        String name = null;
        TextMessage om = (TextMessage) message;
        try {
            if (LOG.isInfoEnabled()) {
                LOG.info("Message Text : " + om.getText());
            }

  User user = UserLocalServiceUtil.getUserById(1L); //some user that exists
  System.out.println("User Name :"+user.getScreenName());

        } catch (Exception e) {
            LOG.error(e);
            throw new EJBException(e); //rollback
        }
    }


}


Once this is all bundled as an ear and deployed you should be able to send a message to the queue and see your output.

Saturday, January 15, 2011

AXIS wsdl2java POM


<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>liferayIntegration</groupId>
<artifactId>liferayIntegration</artifactId>
<version>1.0</version>
 <build>
 <plugins>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>axistools-maven-plugin</artifactId>
<version>1.4</version>
<configuration>
<sourceDirectory>${basedir}/src/main/wsdl</sourceDirectory>
<wsdlFiles>
<wsdlFile>Portal_CompanyService.wsdl</wsdlFile>
</wsdlFiles>
<packageSpace>com.example.generated</packageSpace>
<testCases>false</testCases>
<serverSide>true</serverSide>
<subPackageByFileName>true</subPackageByFileName>
</configuration>
<executions>
<execution>
<goals>
<goal>wsdl2java</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
<dependencies>
<dependency>
<groupId>org.apache.axis</groupId>
<artifactId>axis</artifactId>
<version>1.4</version>
</dependency>
<dependency>
<groupId>javax.xml</groupId>
<artifactId>jaxrpc-api</artifactId>
<version>1.1</version>
</dependency>
<dependency>
<groupId>javax.mail</groupId>
<artifactId>mail</artifactId>
<version>1.4.1</version>
</dependency>
<dependency>
<groupId>javax.activation</groupId>
<artifactId>activation</artifactId>
<version>1.1</version>
</dependency>
</dependencies>
</project>