Showing posts with label web app. Show all posts
Showing posts with label web app. Show all posts

Monday, 11 August 2014

Embedded jetty server with web app

Recently, I come across a situation where both maven-jetty plugin & embedded jetty server need to packed along with web-application. I have already written a blog on incorporating maven-jetty plugin in the web app here, hence will not be discussing here again. I will describe here about package of embedded jetty server with in web application below.

Firstly, why do we require to include embedded jetty?
1. Easy deployment, java -jar <web-app>.jar, once you build the artifact, it's ready for deployment without any hassle configurations/deployment procedures, etc
2. No requirement of application server.


Let's go through the following steps to include jetty server within web app.

1. Create a JettyServer class


package com.sateesh.application.server;

import org.eclipse.jetty.server.Connector;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.ServerConnector;
import org.eclipse.jetty.servlet.DefaultServlet;
import org.eclipse.jetty.servlet.ServletHolder;
import org.eclipse.jetty.util.thread.QueuedThreadPool;
import org.eclipse.jetty.webapp.WebAppContext;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.servlet.DispatcherServlet;

import java.io.IOException;


public class JettyServer {

    private static final Logger logger = LoggerFactory.getLogger(JettyServer.class);
    private final String WEB_APP_DIR = "src/main/webapp";
    private final String WEB_XML_PATH = "src/main/webapp/WEB-INF/web.xml";
    private static final String MVC_SERVLET_NAME = "dispatcher";
    private static final String JSP_SERVLET_NAME = "jspServlet";
    private static final String DEFAULT_PORT = "8080";
    private static final String DEFAULT_CONTEXT_PATH = "/";



    public static void main(String[] args) throws Exception{
        JettyServer jettyServer = new JettyServer();
        jettyServer.start();
    }

    private JettyServer() {

      // none can instantiate this class
    }

    private void start() throws Exception{
        try {
            QueuedThreadPool threadPool = new QueuedThreadPool(512);

            final Server server = new Server(threadPool);
            server.setStopAtShutdown(true);
            server.setStopTimeout(5000);

            ServerConnector connector = new ServerConnector(server);
            connector.setPort(getPort());
            connector.setIdleTimeout(30000);
            server.setConnectors(new Connector[]{connector});
            server.setHandler(getServletContextHandler());

            server.start();
            server.join();
            logger.info("Embedded Jetty Server is started!");
        } catch (Exception e) {
            logger.error("Exception occurred while starting the jetty server ", e);
        }
    }

    private WebAppContext getServletContextHandler() throws IOException {
        final WebAppContext contextHandler = new WebAppContext();
        contextHandler.setContextPath(getContextPath());
        contextHandler.setWar(WEB_APP_DIR);
        contextHandler.setDefaultsDescriptor(WEB_XML_PATH);
        ServletHolder jspServletHolder = new ServletHolder("jspServlet", new org.apache.jasper.servlet.JspServlet());

        // jsp servelet is required to parse the jsp passed by the spring-mvc  
        contextHandler.addServlet(jspServletHolder, "*.jsp");
        return contextHandler;
    }

 

  /**
  * Consider default port as "8080" until unless not passed using java args
  **/  private int getPort() {
        Integer port = Integer.parseInt(System.getProperty("jetty.port"));

        if (port == null || port == 0) {
            port = Integer.parseInt(DEFAULT_PORT);
        }

        return port;
    }

    

  /**
  * Consider default context path as "/" until unless not passed using java args
  **/
  private String getContextPath() {
        String contextPath = System.getProperty("jetty.contextPath");

        if (contextPath == null ||  contextPath.equals("")) {
            contextPath = DEFAULT_CONTEXT_PATH;
        }

        return contextPath;
    }

}



2. Contents of web.xml (default descriptor executed by JettyServer).

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
        "http://java.sun.com/dtd/web-app_2_3.dtd">
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xmlns="http://java.sun.com/xml/ns/javaee"
        xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
        id="YourWebAppID"
        version="2.5">

    <display-name>Web App Server</display-name>

    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>

    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>
            classpath:META-INF/spring/application-context.xml
        </param-value>
    </context-param>

    <servlet>
        <servlet-name>dispatcher</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>classpath:dispatcher-servlet.xml</param-value>
        </init-param>
        <load-on-startup>1</load-on-startup>
    </servlet>

    <servlet-mapping>
        <servlet-name>dispatcher</servlet-name>
        <url-pattern>/api/*</url-pattern>
    </servlet-mapping>

</web-app>



3. Contents of application-context.xml & dispatcher-servlet.xml files

application-context.xml --- is spring descriptor file. 
dispatcher-servlet.xml --- is servlet dispatcher file, which will scan @Controller annotated packages.


4. Package structure of the project

   --- src
       --- main
           --- java 
               --- com.sateesh.application.server
           --- resources
               --- META-INF
                   --- spring
                       --- application-context.xml
               --- dispatcher-servlet.xml
               --- logback.xml
           --- webapp
               --- views
                   ---  ***.jsp
               --- web.xml


5. below plugin needs to be added in pom.xml

            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-shade-plugin</artifactId>
                <version>2.3</version>
                <executions>
                    <execution>
                        <phase>package</phase>
                        <goals>
                            <goal>shade</goal>
                        </goals>
                        <configuration>
                            <filters>
                                <filter>
                                    <artifact>*:*</artifact>
                                    <excludes>
                                        <exclude>META-INF/*.SF</exclude>
                                        <exclude>META-INF/*.DSA</exclude>
                                        <exclude>META-INF/*.RSA</exclude>
                                    </excludes>
                                </filter>
                            </filters>
                            <createDependencyReducedPom>true</createDependencyReducedPom>
                            <transformers>
                                <transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
                                    <mainClass>com.sateesh.application.server.JettyServer</mainClass>
                                </transformer>
                            </transformers>
                        </configuration>
                    </execution>
                </executions>
            </plugin>


6. add below dependencies in pom.xml

    <properties>
        <jetty.server.scope>compile</jetty.server.scope>
        <jetty.version>9.1.2.v20140210</jetty.version>
    </properties>


        <dependency>
            <groupId>org.eclipse.jetty</groupId>
            <artifactId>jetty-server</artifactId>
            <version>${jetty.version}</version>
            <scope>${jetty.server.scope}</scope>
        </dependency>
        <dependency>
            <groupId>org.eclipse.jetty</groupId>
            <artifactId>jetty-webapp</artifactId>
            <version>${jetty.version}</version>
            <scope>${jetty.server.scope}</scope>
        </dependency>
        <dependency>
            <groupId>org.eclipse.jetty</groupId>
            <artifactId>jetty-servlet</artifactId>
            <version>${jetty.version}</version>
            <scope>${jetty.server.scope}</scope>
        </dependency>
        <dependency>
            <groupId>org.eclipse.jetty</groupId>
            <artifactId>jetty-jsp</artifactId>
            <version>${jetty.version}</version>
            <scope>${jetty.server.scope}</scope>
        </dependency>


7. You are almost there.. now run the web application now.

build the project (default package is jar in maven):
mvn clean package

run the webapp:
java -jar target/webapp.jar


PS: we can also create embedded jetty server with in web-app without web.xml file also.

Thursday, 4 July 2013

Tiles framework for Jsps

I am here with the introduction of tiles framework for Java Servlet Page (JSP)s. I am not giving the information on integration of tiles with sturts/spring here. It is simple tiles usage with jsps.

Following the steps. Considering web app is build by maven tool, tiles version is 2.1.2.

1. Maven dependencies required to include in the project object model file pom.xml


       <dependency>
            <groupId>org.apache.tiles</groupId>
            <artifactId>tiles-extras</artifactId>
            <version>2.2.2</version>
        </dependency>
        <dependency>
            <groupId>org.apache.tiles</groupId>
            <artifactId>tiles-core</artifactId>
            <version>2.1.2</version>
        </dependency>
        <dependency>
            <groupId>org.apache.tiles</groupId>
            <artifactId>tiles-servlet</artifactId>
            <version>2.1.2</version>
        </dependency>
        <dependency>
            <groupId>org.apache.tiles</groupId>
            <artifactId>tiles-jsp</artifactId>
            <version>2.1.2</version>
        </dependency>
        <dependency>
            <groupId>org.apache.tiles</groupId>
            <artifactId>tiles-api</artifactId>
            <version>2.1.2</version>
        </dependency>


2. Modifications in web descriptor file web.xml


    <!-- listener needs to be added for tiles -->

    <listener>
        <listener-class>org.apache.tiles.web.startup.TilesListener</listener-class>
    </listener>


    <!-- servlet needs to be added for tiles -->


    <servlet>
        <servlet-name>tiles</servlet-name>
        <servlet-class>org.apache.tiles.web.startup.TilesServlet</servlet-class>
        <init-param>
            <param-name>
                org.apache.tiles.impl.BasicTilesContainer.DEFINITIONS_CONFIG
            </param-name>
            <param-value>
                /WEB-INF/tiles-defs.xml
            </param-value>
        </init-param>
        <load-on-startup>3</load-on-startup>
    </servlet>


3. Add a tiles descriptor file tiles-defs.xml file


<?xml version="1.0" encoding="ISO-8859-1" ?>
<!DOCTYPE tiles-definitions PUBLIC "-//Apache Software Foundation//DTD Tiles Configuration 2.1//EN"
        "http://tiles.apache.org/dtds/tiles-config_2_1.dtd">
<tiles-definitions>

    <definition name="unauthorized_default" template="/appName/templates/layout.jsp">
        <put-attribute name="header" value="/appName/templates/nonAuthenticatedHeader.jsp" />
        <put-attribute name="menu" value="/appName/templates/menu.jsp" />
        <put-attribute name="body" value="/appName/templates/body.jsp" />
        <put-attribute name="footer" value="/appName/templates/footer.jsp" />
    </definition>

    <definition name="authorized_default" template="/appName/templates/layout.jsp">
        <put-attribute name="header" value="/appName/templates/header.jsp" />
        <put-attribute name="menu" value="/appName/templates/menu.jsp" />
        <put-attribute name="body" value="/appName/templates/body.jsp" />
        <put-attribute name="footer" value="/appName/templates/footer.jsp" />
    </definition>

    <definition name="authorized_home" template="/appName/templates/layout_leftmenu.jsp">
        <put-attribute name="header" value="/appName/templates/header.jsp" />
        <put-attribute name="menu" value="/appName/templates/menu.jsp" />
        <put-attribute name="leftMenu" value="/appName/templates/leftMenu.jsp" />
        <put-attribute name="body" value="/appName/templates/body.jsp" />
        <put-attribute name="footer" value="/appName/templates/footer.jsp" />
    </definition>

</tiles-definitions>




4. Template files required to add:

(a) layout.jsp

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Frameset//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-frameset.dtd">
<%@ taglib uri="http://tiles.apache.org/tags-tiles" prefix="tiles" %>



      <table width="100%">
      <tr>
        <td>
          <tiles:insertAttribute name="header" />
        </td>
      </tr>
      <tr>
        <td>
          <tiles:insertAttribute name="menu" />
        </td>
      </tr>
      <tr>
        <td>
          <tiles:insertAttribute name="body" />
        </td>
      </tr>
      <tr>
        <td>
          <tiles:insertAttribute name="footer" />
        </td>
      </tr>
    </table>

(b) layout_leftmenu.jsp

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Frameset//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-frameset.dtd">
<%@ taglib uri="http://tiles.apache.org/tags-tiles" prefix="tiles" %>



      <table width="100%">
      <tr>
        <td colspan="2">
          <tiles:insertAttribute name="header" />
        </td>
      </tr>
      <tr>
        <td colspan="2">
          <tiles:insertAttribute name="menu" />
        </td>
      </tr>
      <tr>
        <td width="25%">
          <tiles:insertAttribute name="leftMenu" />
        </td>
        <td>
          <tiles:insertAttribute name="body" />
        </td>
      </tr>
      <tr>
        <td align="center">
          <tiles:insertAttribute name="footer" />
        </td>
      </tr>
    </table>




5. Calling the tiles definitions on any jsp


<html>
<body>
    <div align="center" width="100%">
        <tiles:insertDefinition name="unauthorized_default">
            <tiles:putAttribute name="menu" value="/callCenter/templates/blank.jsp" />
            <tiles:putAttribute name="body" value="/callCenter/loginPage.jsp" />
        </tiles:insertDefinition>
    </div>
</body>
</html>





Thursday, 13 June 2013

Configuration of Jetty-Maven plugin to a web app

In present era development process, everybody is primarily concerned about faster development process, because of which development environment has become vital in the project implementation plan.

Jetty is the one of the light weight application server, which can be run on stand-alone or using maven plugin. I am here giving the configuration details of later one.

(One assumption here is, reader has the knowledge of Maven)

1. Add jetty-maven plugin in the plugins section of pom.xml


           <plugin>
                <groupId>org.mortbay.jetty</groupId>
                <artifactId>jetty-maven-plugin</artifactId>
                <version>8.1.9.v20130131</version>
                <configuration>
                    <connectors>
                        <connector  implementation="org.eclipse.jetty.server.nio.SelectChannelConnector">
                            <port>8080</port>
                        </connector>
                    </connectors>
                    <stopPort>18080</stopPort>
    <scanIntervalSeconds>0</scanIntervalSeconds>
    <webXml>target/classes/web.xml</webXml>
    <webApp>
           <contextPath>/</contextPath>
    </webApp>
                </configuration>
                <dependencies>
                    // any dependencies required can be added here
                    // if you project has dependency on jsf, add jsf dependencies here too.
                </dependencies>
            </plugin>


2. Go to the terminal and change directory to base directory of project and run the server using below command.

mvn jetty:run

PS: Maven Options might need to be mentioned

(i) Perm Genspace attributes:
MAVEN_OPTS="-Xmx1024m -XX:MaxPermSize=256m"

(ii) Starting jetty server in debug mode with Perm Genspace attributes:
MAVEN_OPTS="-Xmx1024m -XX:MaxPermSize=256m -Xdebug -Xnoagent -Djava.compiler=NONE -Xrunjdwp:transport=dt_socket,address=4000,server=y,suspend=y"