Virgo recipe "Serving Web Content with Spring MVC"

Virgo Homepage

Acknowledgements

This guide is inspired by "Serving Web Content with Spring MVC" from the Spring Guides.

Serving Web Content with Spring MVC

The original guide uses Spring Boot to bootstrap the demo application. This guide shows what needs to be done to serve web content with Virgo.

Shopping list

Note

Only Virgo Server for Apache Tomcat and Virgo Jetty Server are supported by the Virgo Tooling.

Ingredients

Preparations

Get the code

Clone the code from the Git repository: Sample Git repository:

$ cd ~/MyAwesomeProjectDirectory/
$ git clone git://git.eclipse.org/gitroot/virgo/org.eclipse.virgo.samples.git
$ cd org.eclipse.virgo.samples
$ cd recipe-serving-web-content

Once inside the source directory of this recipe - your are good to go.

Create the Custom Virgo Runtime

Create your own Virgo runtime with Gradle and Dockerizor:

$ ./gradlew :recipe-serving-web-content-runtime dockerize

The custom Virgo Runtime is packaged as tar archive and available from the runtime build directory. Extract the runtime into some directory - let’s say into VIRGO_HOME.

Caution

You’ll need a Docker daemon running in order to create your custom Virgo runtime. For more information please refer to the Dockerizor documentation.

Create Eclipse Project Metadata

Create the Eclipse IDE metadata with:

$ ./gradlew eclipse

Prepare the Virgo Tooling

Download Eclipse IDE for Java EE Developers e.g. Eclipse Mars.2 (4.5.2).

Start your Eclipse IDE and add the Virgo Tooling to your Eclipse IDE.

Optionally add the Docker Tooling to your Eclipse IDE.

Import the code into your Eclipse IDE

Now you can Import ▸ Gradle ▸ Gradle Project into your IDE. The project folder is called recipe-serving-web-content and lies directly in the "Sample Applications" folder you created previously with the Git clone command. (org.eclipse.virgo.samples).

Note

Before you can drag’n’drop the project onto your freshly created Virgo Server you might have to execute Virgo ▸ Run Generation of META-INF/MANIFEST.MF (via a right click on the project) within your Eclipse IDE.

Create new Virgo Server Runtime

Define a new server

Within the IDE New ▸ Server ▸ EclipseRT ▸ Virgo Runtime and choose the directory of the previously installed Virgo server VIRGO_HOME.

Directions

Virgo has no support for Spring’s @EnableAutoConfiguration, so you have to be more explicit than in the Spring Boot version of this guide - after all, Virgo is an OSGi runtime and every bundle needs to declare its needs in the META-INF/MANIFEST.MF.

Basically, you have to specify necessary dependencies (via Import-Package or Import-Bundle headers) and the Web-ContextPath the REST service application wants to be published on.

The Manifest template

template.mf
Bundle-Version: 0.1
Bundle-Name: Virgo Recipe Serving Web Content
Bundle-SymbolicName: org.eclipse.virgo.samples.recipe.web
Web-ContextPath: /thymeleaf
Bundle-ClassPath: .
Import-Package: org.eclipse.virgo.web.dm,
 org.springframework.web.servlet.config,
 javax.servlet,
 javax.servlet.http,
 org.thymeleaf,
 org.thymeleaf.templateresolver,
 org.thymeleaf.spring4,
 org.thymeleaf.spring4.context,
 org.thymeleaf.spring4.dialect,
 org.thymeleaf.spring4.expression,
 org.thymeleaf.spring4.messageresolver,
 org.thymeleaf.spring4.naming,
 org.thymeleaf.spring4.processor.attr,
 org.thymeleaf.spring4.requestdata,
 org.thymeleaf.spring4.resourceresolver,
 org.thymeleaf.spring4.templateresolver,
 org.thymeleaf.spring4.util,
 org.thymeleaf.spring4.view
Import-Bundle: org.springframework.aop,
 org.springframework.beans,
 org.springframework.core,
 org.springframework.context,
 org.springframework.context.support,
 org.springframework.expression,
 org.springframework.web,
 org.springframework.webmvc

You can mix and match the Virgo specific header Import-Bundle and OSGi standard header Import-Package.

Compatibility

In the sample the fine-tuning of the MANIFEST.MF is done within the template.mf.

Note

If you intend to run your bundles in different OSGi containers you have to limit yourself to the OSGi standard headers.

The web.xml configuration

Next step is to configure the servlet container via

WEB-INF/web.xml
<?xml version="1.0" encoding="ISO-8859-1"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
	xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
	version="2.5">

	<!-- The definition of the Root Spring Container shared by all Servlets and Filters -->
	<context-param>
		<param-name>contextConfigLocation</param-name>
		<param-value>/WEB-INF/spring/root-context.xml</param-value>
	</context-param>

    <context-param>
        <param-name>contextClass</param-name>
        <param-value>org.eclipse.virgo.web.dm.ServerOsgiBundleXmlWebApplicationContext</param-value>
    </context-param>

	<!-- Creates the Spring Container shared by all Servlets and Filters -->
	<listener>
		<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
	</listener>

	<!-- Processes application requests -->
	<servlet>
		<servlet-name>appServlet</servlet-name>
		<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
		<init-param>
			<param-name>contextConfigLocation</param-name>
			<param-value>/WEB-INF/spring/appServlet/servlet-context.xml</param-value>
		</init-param>
		<load-on-startup>1</load-on-startup>
	</servlet>

	<servlet-mapping>
		<servlet-name>appServlet</servlet-name>
		<url-pattern>/</url-pattern>
	</servlet-mapping>
</web-app>

closer look at web.xml

Caution

The most important parameter is the contextClass

It’s not the default from the Spring Framework, but Virgo’s ServerOsgiBundleXmlWebApplicationContext.

<context-param>
    <param-name>contextClass</param-name>
    <param-value>org.eclipse.virgo.web.dm.ServerOsgiBundleXmlWebApplicationContext</param-value>
</context-param>

Let’s taste

Start the Virgo server inside the Springsource Tool Suite to appreciate what you build. With curl and the command line simply run the following command within the project’s directory:

$ curl -i 'http://localhost:8080/thymeleaf/?name=Virgo'

You should see an output like:

<body>
    <p>Hello, Virgo!</p>
</body>

or point your favorite browser to http://localhost:8080/thymeleaf/

Dockerise the Application

We use Gradle and Dockerizor to build the application. Instead of running the sample within the Eclipse IDE you can build a Docker image:

$ ./gradlew dockerize

and run the application with:

$ docker run