Skip to main content

Maven and seam project on tomcat

One of my first web projects with Java was a seam project running on the tomcat. At a time when we worked on this project (in 2009) there was not lots of advice how to properly configured seam to runs on tomcat using maven. Also manufacturer recommend using of JBoss and Tomcat is only recommend as testing platform.

Some days ago I have chatted with my colleague about configuring seam framework on the JBoss, and of course on the net you can find a lot advices and instructions, what not surprise me, because this is recommended choice by manufacturer. But that encourage me to research a net one more time and check is situation with tomcat changed after two years. But on my surprise, the list of useful posts with this topic is not much increased by the time when we used tomcat and seam.



In this post I will not write about manev, tomcat or seam, i will base only on project configuration. If you want to get more info about seam, maven and tomcat follow next links:
Configuration of maven project

For this example we will use next project structure:
  • parent
    • model
    • services
    • web
Parent project

If we want to create seam project with maven we should use jboss seam as the parent of our project and on that way we will get configured dependency management 


So to do this we need to add next in our parent pom:



<parent>
    <artifactId>root</artifactId>
    <groupId>org.jboss.seam</groupId>
    <version>2.1.1.GA</version>
</parent>

<repositories>
    <repository>
        <!-- Setting up JBoss repository-->
        <id>reposirtory.jboss.org</id>
        <url>http://repository.jboss.org/maven2</url>
        <releases>
            <enabled>true</enabled>
        </releases>
        <snapshots>
            <enabled>false</enabled>
        </snapshots>
    </repository>
</repositories>



Also, if we want to create seam project, we need to setup project to use at least Java 5, because earlier version do not support annotations, and that is reason why we need to configure maven compiler plugin:


<plugin>
    <artifactId>maven-compiler-plugin</artifactId>
    <version>2.0.2</version>
    <configuration>
<!-- Set up version of Java, at least it need to be 1.5 (older version do not support annotation ) -->
<source>1.6</source>
<target>1.6</target>
    </configuration>
</plugin>

This is example of simple parent project for seam project:


<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/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>ba.codecentric</groupId>
<artifactId>app</artifactId>
<packaging>pom</packaging>
<name>parent</name>
<version>0.0.1-SNAPSHOT</version>
<!-- Include all seam dependencies, dependency-management are already configured -->
<parent>
    <artifactId>root</artifactId>
    <groupId>org.jboss.seam</groupId>
    <version>2.1.1.GA</version>
</parent>
<modules>
    <module>app.model</module>
    <module>app.services</module>
    <module>app.web</module>
</modules>
<build>
    <plugins>
        <plugin>
            <artifactId>maven-compiler-plugin</artifactId>
            <version>2.0.2</version>
            <configuration>
                <!-- Set up version of Java, at least it need to be 1.5 (older version do not support annotation ) -->
                <source>1.6</source>
                <target>1.6</target>
            </configuration>
        </plugin>
    </plugins>
</build>
<repositories>
    <repository>
        <!-- Setting up JBoss repository-->
        <id>reposirtory.jboss.org</id>
        <url>http://repository.jboss.org/maven2</url>
        <releases>
            <enabled>true</enabled>
        </releases>
        <snapshots>
            <enabled>false</enabled>
        </snapshots>
    </repository>
</repositories>
</project>


Model project


Next is example of model project:



<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/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>ba.codecentric.evidencija</groupId>
<artifactId>app.model</artifactId>
<name>data model</name>
<version>0.0.1-SNAPSHOT</version>
<parent>
    <artifactId>app</artifactId>
    <groupId>ba.codecentric</groupId>
    <version>0.0.1-SNAPSHOT</version>
</parent>
<dependencies>
    <dependency>
        <groupId>javax.persistence</groupId>
        <artifactId>persistence-api</artifactId>
    </dependency>
    <dependency>
        <groupId>commons-collections</groupId>
        <artifactId>commons-collections</artifactId>
    </dependency>
    <dependency>
        <groupId>org.jboss.seam</groupId>
        <artifactId>jboss-seam</artifactId>
        <type>ejb</type>
    </dependency>
</dependencies>
</project>

Service project


<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/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>ba.codecentric</groupId>
<artifactId>app.services</artifactId>
<name>services</name>
<version>0.0.1-SNAPSHOT</version>
<parent>
    <artifactId>app</artifactId>
    <groupId>ba.codecentric</groupId>
    <version>0.0.1-SNAPSHOT</version>
</parent>
<dependencies>
    <!-- Include model project -->
    <dependency>
        <groupId>de.codecentric</groupId>
        <artifactId>fourtexx.evaluation.model</artifactId>
        <version>1.0.6-SNAPSHOT</version>
    </dependency>
    <dependency>
        <groupId>org.jboss.seam</groupId>
        <artifactId>jboss-seam-ui</artifactId>
    </dependency>
    <dependency>
        <groupId>org.hibernate</groupId>
        <artifactId>hibernate-validator</artifactId>
    </dependency>
    <dependency>
        <groupId>org.hibernate</groupId>
        <artifactId>hibernate-entitymanager</artifactId>
    </dependency>
    <dependency>
        <groupId>javax.faces</groupId>
        <artifactId>jsf-api</artifactId>
    </dependency>
    <dependency>
        <groupId>com.sun.facelets</groupId>
        <artifactId>jsf-facelets</artifactId>
    </dependency>
</dependencies>
</project>

Web project

<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/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>ba.codecentric</groupId>
<artifactId>app.web</artifactId>
<packaging>war</packaging>
<name>web</name>
<version>0.0.1-SNAPSHOT</version>
<parent>
    <artifactId>evidencija</artifactId>
    <groupId>ba.codecentric.evidencija</groupId>
    <version>0.0.1-SNAPSHOT</version>
</parent>
<dependencies>
<dependency>
    <groupId>ba.codecentric</groupId>
        <artifactId>app.services</artifactId>
        <version>0.0.1-SNAPSHOT</version>
        <exclusions>
                <!-- excluding el-api, because it is already provided by tomcat. -->
                <exclusion>
                        <groupId>javax.el</groupId>
                        <artifactId>el-api</artifactId>
                </exclusion>
        </exclusions>
</dependency>
<dependency>
    <groupId>javassist</groupId>
    <artifactId>javassist</artifactId>
</dependency>
<dependency>
    <groupId>javax.transaction</groupId>
    <artifactId>jta</artifactId>
</dependency>
<!-- tomcat has no jsf implementation by default -->
<dependency>
    <groupId>javax.faces</groupId>
    <artifactId>jsf-impl</artifactId>
</dependency>
<dependency>
    <groupId>javax.faces</groupId>
    <artifactId>jsf-api</artifactId>
</dependency>
<dependency>
    <groupId>org.richfaces.framework</groupId>
    <artifactId>richfaces-api</artifactId>
</dependency>
<dependency>
    <groupId>org.richfaces.framework</groupId>
    <artifactId>richfaces-impl</artifactId>
</dependency>
<dependency>
    <groupId>org.richfaces.ui</groupId>
    <artifactId>richfaces-ui</artifactId>
</dependency>
<dependency>
    <groupId>com.sun.facelets</groupId>
    <artifactId>jsf-facelets</artifactId>
</dependency>
</dependencies>
</project>

Configuration of Seam

When we done with creation of base project structure, we need to configure seam.
First we need to create "seam.properties" file which we will root in the root folder of project. This file is empty, and usually it is inside of service project in the "src/main/recources" folder.
Next what is need to be done is creating of "components.xml" file. This file contains information about seam configuration and also we can use it to create components if we do not want to use annotation.
This file we put inside of the "src/main/recoutce/META-INF" folder.

Simple example of "components.xml" file:

<?xml version="1.0" encoding="UTF-8"?>
<components xmlns="http://jboss.com/products/seam/components"
                                xmlns:core="http://jboss.com/products/seam/core"                                 xmlns:persistence="http://jboss.com/products/seam/persistence"                              xmlns:transaction="http://jboss.com/products/seam/transaction"
                                xmlns:web="http://jboss.com/products/seam/web" 
                                xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"                                xsi:schemaLocation="http://jboss.com/products/seam/core http://jboss.com/products/seam/core-2.1.xsd                                                              http://jboss.com/products/seam/persistence http://jboss.com/products/seam/persistence-2.1.xsd                                                         http://jboss.com/products/seam/transaction http://jboss.com/products/seam/transaction-2.1.xsd                                                            http://jboss.com/products/seam/components http://jboss.com/products/seam/components-2.1.xsd                                                            http://jboss.com/products/seam/web http://jboss.com/products/seam/web-2.1.xsd">
<!-- Setting up conversation timeout , request timeout and conversation id  -->
<core:manager conversation-timeout="120000" concurrent-request-timeout="500" conversation-id-parameter="cid" />
<!-- Transaction is disabled because we don't need it for now-->
<transaction:no-transaction/>
<web:multipart-filter max-request-size="100000000" create-temp-files="false" />
</components>

After this we need to configure web.xml file so we can use seam also for web. Example of web.xml which also contains needed configuration for RichFaces and JSF:

<web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
                   http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
<!-- Seam -->
<listener>
    <listener-class>org.jboss.seam.servlet.SeamListener</listener-class>
</listener>
<filter>
    <filter-name>Seam Filter</filter-name>
    <filter-class>org.jboss.seam.servlet.SeamFilter</filter-class>
</filter>
<filter-mapping>
    <filter-name>Seam Filter</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>
<servlet>
    <servlet-name>Seam Resource Servlet</servlet-name>
    <servlet-class>org.jboss.seam.servlet.SeamResourceServlet</servlet-class>
</servlet>
<servlet-mapping>
    <servlet-name>Seam Resource Servlet</servlet-name>
    <url-pattern>/seam/resource/*</url-pattern>
</servlet-mapping>
<!-- Faces Servlet -->
<servlet>
    <servlet-name>Faces Servlet</servlet-name>
    <servlet-class>javax.faces.webapp.FacesServlet</servlet-class>
    <load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
    <servlet-name>Faces Servlet</servlet-name>
    <url-pattern>*.seam</url-pattern>
</servlet-mapping>
<!-- JSF parameters -->
<context-param>
    <param-name>javax.faces.DEFAULT_SUFFIX</param-name>
    <param-value>.xhtml</param-value>
</context-param>
<context-param>
    <param-name>facelets.DEVELOPMENT</param-name>
    <param-value>true</param-value>
</context-param>
<session-config>
    <session-timeout>50</session-timeout>
</session-config>
<!-- Configuring richfaces -->
<context-param>
    <param-name>org.richfaces.SKIN</param-name>
    <param-value>classic</param-value>
</context-param>
<context-param>
    <param-name>org.ajax4jsf.VIEW_HANDLERS</param-name>
    <param-value>com.sun.facelets.FaceletViewHandler</param-value>
</context-param>
<filter>
    <display-name>RichFaces Filter</display-name>
    <filter-name>richfaces</filter-name>
    <filter-class>org.ajax4jsf.Filter</filter-class>
</filter>
<filter-mapping>
    <filter-name>richfaces</filter-name>
    <servlet-name>Faces Servlet</servlet-name>
    <dispatcher>REQUEST</dispatcher>
    <dispatcher>FORWARD</dispatcher>
    <dispatcher>INCLUDE</dispatcher>
</filter-mapping>
</web-app>

And also there is configuration of faces-config.xml:

<?xml version="1.0" encoding="UTF-8"?>
<faces-config version="1.2" xmlns="http://java.sun.com/xml/ns/javaee"
                                xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
                                xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-facesconfig_1_2.xsd">
<!-- Facelets support -->
<application>
        <view-handler>com.sun.facelets.FaceletViewHandler</view-handler>
</application>
</faces-config>

Comments

Popular posts from this blog

Checking file's "magic numbers"

Few days ago I had very interesting task. Our customer required that we perform checking of so called file's "magic numbers" to determinate does uploaded file correspond to it's extension.  We are already allowed only to upload files with some predefined extensions (PDF, DOC ...). But this can not prevent some evil user to update an exe file after renaming it to PDF or DOC. So first of all I will explain what are "magic numbers", and then I will show how we handle them.

Running Spring Boot Web App on the Random Port from Port Range

By default the spring boot web application is listening on the port 8080 for the incoming connection. This behavior can be changed by providing server.port property value during starting of the application or as part of the application.properties or through the code by implementing EmbeddedServletContainerCustomizer. But it would be even better if we could specified a range of the ports which can be used for the starting the application. It would be great if I could specify a property like server.portRange=8100..8200 to define a list of the port on which I want to start my service. In this blog post I will describe how this can be done.

Simple Workflow Engine With Spring

Few months ago, during working on one of the company project, we had need to developed  REST services which is used for sending an email depending on data sent by client application. During developing this service we decide to create simple workflow engine which will be charged for sending an email, but also this engine can be used for any kind of simple flows. In this article i will explain step by step how you can implement your simple workflow engine which can handle sequence flow.