Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Make EL work with tomcat 7 embedded (using spring MVC)

I made an example, available on github, that uses tomcat embedded to boot a simple spring MVC application. The application boot with apparently no problem, but in the rendered jsp, el expression is not processed.

Here is my pom.xml :

<?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/maven-v4_0_0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>com.example</groupId>
    <artifactId>springtomcatembedded</artifactId>
    <name>SpringMVCTomcatEmbedded</name>
    <packaging>war</packaging>
    <version>1.0.0-BUILD-SNAPSHOT</version>
    <properties>
        <java-version>1.6</java-version>
        <org.springframework-version>3.1.1.RELEASE</org.springframework-version>
        <org.aspectj-version>1.6.10</org.aspectj-version>
        <org.slf4j-version>1.6.6</org.slf4j-version>
        <tomcat.version>7.0.50</tomcat.version>
    </properties>
    <dependencies>
        <!-- Spring -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>${org.springframework-version}</version>
            <exclusions>
                <!-- Exclude Commons Logging in favor of SLF4j -->
                <exclusion>
                    <groupId>commons-logging</groupId>
                    <artifactId>commons-logging</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-webmvc</artifactId>
            <version>${org.springframework-version}</version>
        </dependency>

        <!-- AspectJ -->
        <dependency>
            <groupId>org.aspectj</groupId>
            <artifactId>aspectjrt</artifactId>
            <version>${org.aspectj-version}</version>
        </dependency>

        <!-- Logging -->
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-api</artifactId>
            <version>${org.slf4j-version}</version>
        </dependency>
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>jcl-over-slf4j</artifactId>
            <version>${org.slf4j-version}</version>
            <scope>runtime</scope>
        </dependency>
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-log4j12</artifactId>
            <version>${org.slf4j-version}</version>
            <scope>runtime</scope>
        </dependency>
        <dependency>
            <groupId>log4j</groupId>
            <artifactId>log4j</artifactId>
            <version>1.2.15</version>
            <exclusions>
                <exclusion>
                    <groupId>javax.mail</groupId>
                    <artifactId>mail</artifactId>
                </exclusion>
                <exclusion>
                    <groupId>javax.jms</groupId>
                    <artifactId>jms</artifactId>
                </exclusion>
                <exclusion>
                    <groupId>com.sun.jdmk</groupId>
                    <artifactId>jmxtools</artifactId>
                </exclusion>
                <exclusion>
                    <groupId>com.sun.jmx</groupId>
                    <artifactId>jmxri</artifactId>
                </exclusion>
            </exclusions>
            <scope>runtime</scope>
        </dependency>

        <!-- @Inject -->
        <dependency>
            <groupId>javax.inject</groupId>
            <artifactId>javax.inject</artifactId>
            <version>1</version>
        </dependency>

        <!-- Servlet -->
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>javax.servlet-api</artifactId>
            <version>3.0.1</version>
            <scope>provided</scope>
        </dependency>
        <dependency>
            <groupId>javax.servlet.jsp</groupId>
            <artifactId>jsp-api</artifactId>
            <version>2.2</version>
            <scope>provided</scope>
        </dependency>
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>jstl</artifactId>
            <version>1.2</version>
            <scope>provided</scope>
        </dependency>

        <!-- Embedded tomcat -->
        <dependency>
            <groupId>org.apache.tomcat.embed</groupId>
            <artifactId>tomcat-embed-core</artifactId>
            <version>${tomcat.version}</version>
        </dependency>
        <dependency>
            <groupId>org.apache.tomcat.embed</groupId>
            <artifactId>tomcat-embed-logging-juli</artifactId>
            <version>${tomcat.version}</version>
        </dependency>
        <dependency>
            <groupId>org.apache.tomcat.embed</groupId>
            <artifactId>tomcat-embed-jasper</artifactId>
            <version>${tomcat.version}</version>
        </dependency>
        <dependency>
            <groupId>org.apache.tomcat</groupId>
            <artifactId>tomcat-jasper</artifactId>
            <version>${tomcat.version}</version>
        </dependency>
        <dependency>
            <groupId>org.apache.tomcat</groupId>
            <artifactId>tomcat-jasper-el</artifactId>
            <version>${tomcat.version}</version>
        </dependency>
        <dependency>
            <groupId>org.apache.tomcat</groupId>
            <artifactId>tomcat-el-api</artifactId>
            <version>${tomcat.version}</version>
        </dependency>
        <dependency>
            <groupId>org.apache.tomcat</groupId>
            <artifactId>tomcat-jsp-api</artifactId>
            <version>${tomcat.version}</version>
        </dependency>

        <!-- Test -->
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.7</version>
            <scope>test</scope>
        </dependency>
    </dependencies>
    <build>
        <plugins>
            <plugin>
                <artifactId>maven-eclipse-plugin</artifactId>
                <version>2.9</version>
                <configuration>
                    <additionalProjectnatures>
                        <projectnature>org.springframework.ide.eclipse.core.springnature</projectnature>
                    </additionalProjectnatures>
                    <additionalBuildcommands>
                        <buildcommand>org.springframework.ide.eclipse.core.springbuilder</buildcommand>
                    </additionalBuildcommands>
                    <downloadSources>true</downloadSources>
                    <downloadJavadocs>true</downloadJavadocs>
                </configuration>
            </plugin>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>2.5.1</version>
                <configuration>
                    <source>1.6</source>
                    <target>1.6</target>
                    <compilerArgument>-Xlint:all</compilerArgument>
                    <showWarnings>true</showWarnings>
                    <showDeprecation>true</showDeprecation>
                </configuration>
            </plugin>
            <plugin>
                <groupId>org.codehaus.mojo</groupId>
                <artifactId>exec-maven-plugin</artifactId>
                <version>1.2.1</version>
                <configuration>
                    <mainClass>org.test.int1.Main</mainClass>
                </configuration>
            </plugin>
        </plugins>
    </build>
</project>

And here is my main spring controller wich contains also my main method :

package com.example.springtomcatembedded;

import java.io.File;
import java.text.DateFormat;
import java.util.Date;
import java.util.Locale;

import org.apache.catalina.Context;
import org.apache.catalina.LifecycleException;
import org.apache.catalina.Wrapper;
import org.apache.catalina.deploy.ApplicationListener;
import org.apache.catalina.deploy.ApplicationParameter;
import org.apache.catalina.startup.Tomcat;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.servlet.DispatcherServlet;

/**
 * Handles requests for the application home page.
 */
@Controller
public class HomeController {

    private static final Logger logger = LoggerFactory.getLogger(HomeController.class);

    /**
     * Simply selects the home view to render by returning its name.
     */
    @RequestMapping(value = "/", method = RequestMethod.GET)
    public String home(Locale locale, Model model) {
        logger.info("Welcome home! The client locale is {}.", locale);

        Date date = new Date();
        DateFormat dateFormat = DateFormat.getDateTimeInstance(DateFormat.LONG, DateFormat.LONG, locale);

        String formattedDate = dateFormat.format(date);

        model.addAttribute("serverTime", formattedDate );

        return "home";
    }

    public static void main(String[] args) throws LifecycleException {
        Tomcat tomcat = new Tomcat();
        tomcat.setPort(8080);

        Context ctx = tomcat.addContext("/", new File("src/main/webapp/").getAbsolutePath());
        ApplicationParameter rootContextConfiguration = new ApplicationParameter();
        rootContextConfiguration.setName("contextConfigLocation");
        rootContextConfiguration.setValue("/WEB-INF/spring/root-context.xml");
        ctx.addApplicationParameter(rootContextConfiguration);
        ApplicationListener springApplicationListener = new ApplicationListener("org.springframework.web.context.ContextLoaderListener", false);
        ctx.addApplicationListener(springApplicationListener);

        // Configure dispatcher servlet
        Wrapper wrapper = ctx.createWrapper();
        String servletName = "appServlet";
        wrapper.setName(servletName);
        wrapper.setLoadOnStartup(1);
        wrapper.setServletClass(DispatcherServlet.class.getName());
        wrapper.addInitParameter("contextConfigLocation", "/WEB-INF/spring/appServlet/servlet-context.xml");
        wrapper.setLoadOnStartup(1);

        // Define JspServlet.
        Wrapper jspServlet = ctx.createWrapper();
        jspServlet.setName("jsp");
        jspServlet.setServletClass("org.apache.jasper.servlet.JspServlet");
        jspServlet.addInitParameter("fork", "false");
        jspServlet.addInitParameter("xpoweredBy", "false");
        jspServlet.setLoadOnStartup(2);
        ctx.addChild(jspServlet);
        ctx.addServletMapping("*.jsp", "jsp");

        ctx.addChild(wrapper);
        ctx.addServletMapping("/", servletName);
        tomcat.setSilent(false);
        tomcat.start();
        tomcat.getServer().await();

    }
}

My jsp page :

<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<%@ page session="false" %>
<html>
<head>
    <title>Home</title>
</head>
<body>
<h1>
    Hello world!  
</h1>

<P>  The time on the server is ${serverTime}. </P>
</body>
</html>

And finally, my spring mvc configuration :

<?xml version="1.0" encoding="UTF-8"?>
<beans:beans xmlns="http://www.springframework.org/schema/mvc"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:beans="http://www.springframework.org/schema/beans"
    xmlns:context="http://www.springframework.org/schema/context"
    xsi:schemaLocation="http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd
        http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">

    <!-- DispatcherServlet Context: defines this servlet's request-processing infrastructure -->

    <!-- Enables the Spring MVC @Controller programming model -->
    <annotation-driven />

    <!-- Handles HTTP GET requests for /resources/** by efficiently serving up static resources in the ${webappRoot}/resources directory -->
    <resources mapping="/resources/**" location="/resources/" />

    <!-- Resolves views selected for rendering by @Controllers to .jsp resources in the /WEB-INF/views directory -->
    <beans:bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <beans:property name="prefix" value="WEB-INF/views/" />
        <beans:property name="suffix" value=".jsp" />
    </beans:bean>

    <context:component-scan base-package="com.example.springtomcatembedded" />



</beans:beans>

As I said, it is working, but my jsp pages cannot use el to access model data :S Anyone can see why ? For instance, it will print ${serverTime} instead of the actual server time pushed in the model.

like image 271
baraber Avatar asked Feb 04 '14 14:02

baraber


People also ask

Does spring MVC have embedded Tomcat?

Many Spring Boot starters include default embedded containers. For servlet stack applications, the spring-boot-starter-web includes Tomcat by including spring-boot-starter-tomcat , but you can use spring-boot-starter-jetty or spring-boot-starter-undertow instead.

How does spring boot embedded Tomcat work?

Spring Boot has a complete Tomcat inside. It builds a so-called fat-jar with everything needed inside. You don't need Tomcat installed in your system. BTW: Spring Boot also supports other application servers like Jetty.

Which version of Tomcat is embedded in spring boot?

Tomcat 7 & 8.0 work with Spring Boot, but the default is to use Tomcat 8.5. If you cannot use Tomcat 8.5 (for example, because you are using Java 1.6) you will need to change your classpath to reference a different version.


1 Answers

Try to add:

<%@ page isELIgnored="false" %>

to the header of your jsp page. For example:

<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<%@ page session="false" %>
<%@ page isELIgnored="false" %>
<html>
<head>
    <title>Home</title>
</head>
<body>
<h1>
    Hello world!  
</h1>

<P>  The time on the server is ${serverTime}. </P>
</body>
</html>

EDIT:

Inspired by your comment:

If you want to programmatically enable EL expressions in JSP without loading/definition of a web.xml file you have to add the ContextConfig LifecycleListener:

rootContext.addLifecycleListener(new ContextConfig());

a full workin example (Tomcat embedded 7.0.50 with JDK 1.7):

public static void main(String[] args) throws LifecycleException
{
  // setup server
  final Tomcat tomcat = new Tomcat();
  tomcat.setBaseDir("."); // location where temp dir is created
  tomcat.setPort(8080);

  // configure context
  final File applicationPath = new File("./webapp"); // todo: change to your location
  Context rootContext = tomcat.addContext("/", applicationPath.getAbsolutePath());
  rootContext.addLifecycleListener(new ContextConfig());

  // JSP and Default Servlet setup, mime type mapping and welcome files
  Tomcat.initWebappDefaults(rootContext);

  // start server
  tomcat.start();
  tomcat.getServer().await();
}

with this solution you don't need to explicitly state page directives in your JSP files.

HINT: dont forget to delete your "work" (=temporary tomcat directory) after makin changes and before restarting your server. Compiled JSP's are chached there and you may get old results!

HTH,

like image 121
Chris Avatar answered Nov 28 '22 08:11

Chris