Sunday, December 14, 2008

Simple Web Application with SpringSource dm Server

(Please see the updated tutorial. 2009/03/25)

Finally I got a very simple Web application working with SpringSource dm Server. The goal is to set up a complete Web application development environment with Eclipse as IDE, Maven as build tool, SpringSource dm Server as deployment environment.

The process is very simple, but still took me a lot of time to figure out the best practice.

1. Set up IDE. Extract downloaded eclipse newest version eclipse-jee-ganymede-SR1-win32.zip to S2DM. And install Spring IDE (2.2.1.v200811281800), Spring dm Server Tool (1.1.0.v200811281800). I also installed M2Eclipse plugin (0.9.6.20080905-0917). 
Extract downloaded SpringSource dm Server 1.0.1.RELEASE to S2DM. Set up a server runtime in Eclipse for SpringSource dm Server v1.0 at localhost.

2. Create a new SpringSource dm Server Bundle project in Eclipse. Name is "org.simple.web"
The module type is "Web", context path is "simple", and dispatcher servlet url pattern is "*.htm".

3. After project creation, move the META-INF folder from src/main/jave to src/main/resources folder and add the resources folder to Java build source path in Eclipse.

Update the MANIFEST.MF :
Manifest-Version: 1.0
Bundle-Version: 1.0.0
Bundle-Name: Simple Web Bundle
Bundle-ManifestVersion: 2
Bundle-Description: A very simple Spring DM Web Bundle
Bundle-SymbolicName: org.simple.web
Import-Bundle: com.springsource.javax.servlet
 ,com.springsource.javax.servlet.jsp
 ,com.springsource.org.apache.taglibs.standard
 ,org.springframework.core
 ,org.springframework.beans
 ,org.springframework.context
 ,org.springframework.context.support
 ,org.springframework.web
 ,org.springframework.web.servlet
Module-Type: Web
Web-ContextPath: simple
Web-DispatcherServletUrlPatterns: *.htm
The SpringSource dm Server Tool automatically sets up Bundle Dependencies.
4. Copy spring config files from PetClinic sample project. Create folder src/main/resources/META-INF/spring, and copy module-context.xml, osgi-context.xml.

5. Follow Craig Walls "Spring In Action" Second Edition Chapter 13 Handling wweb request, to create a simple Spring MVC Web application, but using new SpringSource dm Server OSGi-centric web application directory structure.

Create folder "src/main/resources/MODULE-INF", this is the folder for all the web content.

Add index.html to MODULE-INF folder:
<html>
<head>
  <meta http-equiv="Refresh" content="0; URL=home.htm">
</head>
</html>
The index.html redirects to home page "home.htm"

Add a very simple jsp file for the home page, just display welcome messag and list all members from backend:
<%@ page contentType="text/html" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<html
 <head><title>Open Toast</title></head>
 
 <body>
  <h2>Welcome to Open Toast Project</h2>
  
  <h3>Current Members:</h3>
  <ul>
  <c:forEach items="${members}" var="member">
  <li><c:out value="${member.name}"/>
  </li>
  </c:forEach>
  </ul>
 </body>
</html>

And I have to change taglib uri to get rid of this exception:
org.apache.jasper.JasperException: /WEB-INF/jsp/home.jsp(11,2) According to TLD or attribute directive in tag file, attribute items does not accept any expressions

Add Spring MVC controller for home page:
src/main/java/org/simple/web/HomePageController.java
@Controller
@RequestMapping("/home.htm")
public class HomePageController{
  public HomePageController(){}

  @RequestMapping(method=RequestMethod.GET)
  public ModelAndView handleRequest(HttpServletRequest request,
      HttpServletResponse response) throws Exception {
    List members = new ArrayList();
    members.add(new Member("Yuan Ji"));
    return new ModelAndView("home", "members", members);
  }
}
src/main/java/org/simple/web/Member.java
public class Member {
  private String name;

  public Member(String name){
    this.name = name;
  }
  public String getName() {
    return name;
  }

  public void setName(String name) {
    this.name = name;
  }
}
So when redirect to "/home.htm", it will map to HomePageController, and the return view is "home", which is mapped to WEB-INF/jsp/home.jsp

6. Add org.simple.web project to SpringSource dm Server, and start the server.

In Admin Console, you can see the deployed applications include org.simple.web. 

Click the link "/simple", open the simple web application.

4 comments:

CHBIHI LOUHDI Mohammed Reda said...

Hi,

thank you so mush for this example,
but when I lunch the application, it gives me this error :

exception:

javax.servlet.ServletException: Servlet.init() for servlet org.simple.web-DispatcherServlet threw exception
org.apache.catalina.valves.CometConnectionManagerValve.invoke(CometConnectionManagerValve.java:248)
org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:568)
com.springsource.server.servlet.tomcat.internal.ApplicationNameTrackingValve.invoke(ApplicationNameTrackingValve.java:74)
org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:568)
org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:102)
org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:286)
org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:845)
org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:583)
org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:354)
com.springsource.server.concurrent.core.ExecutorServiceDelegate$StatisticsGatheringRunnable.run(ExecutorServiceDelegate.java:137)
com.springsource.server.concurrent.core.ServerThreadPoolExecutor$1.run(ServerThreadPoolExecutor.java:145)
java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:886)
java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:908)
java.lang.Thread.run(Thread.java:619)

root cause:

java.lang.IllegalStateException: No WebApplicationContext found: initializer not registered?
org.springframework.web.servlet.FrameworkServlet.findWebApplicationContext(FrameworkServlet.java:356)
org.springframework.web.servlet.FrameworkServlet.initWebApplicationContext(FrameworkServlet.java:311)
org.springframework.web.servlet.FrameworkServlet.initServletBean(FrameworkServlet.java:282)
org.springframework.web.servlet.HttpServletBean.init(HttpServletBean.java:126)
javax.servlet.GenericServlet.init(GenericServlet.java:212)
org.apache.catalina.valves.CometConnectionManagerValve.invoke(CometConnectionManagerValve.java:248)
org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:568)
com.springsource.server.servlet.tomcat.internal.ApplicationNameTrackingValve.invoke(ApplicationNameTrackingValve.java:74)
org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:568)
org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:102)
org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:286)
org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:845)
org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:583)
org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:354)
com.springsource.server.concurrent.core.ExecutorServiceDelegate$StatisticsGatheringRunnable.run(ExecutorServiceDelegate.java:137)
com.springsource.server.concurrent.core.ServerThreadPoolExecutor$1.run(ServerThreadPoolExecutor.java:145)
java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:886)
java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:908)
java.lang.Thread.run(Thread.java:619)


thank you

Unknown said...

I got the same error and after spending quite some time to get the petclinic example going from inside eclipse I finally registered with springsource's issuetracker and found that issue:

https://issuetracker.springsource.com/browse/PLATFORM-220

Fix-Version for supposed to be 1.0.2.RELEASE, so I guess we still have to wait a bit; unfortunately there's no more comments on that issue...

jiwhiz said...

Hi reda and evandor,

I'm so sorry that I didn't turn on comment notification and didn't know your comments.

I was struggling with Maven, BND and dm Server Tool for so long and almost gave up. Now SpringSource released Bundlor, and I will give it another try.

I will update the Tutorial this weekend with new blog.

Thank you for being interested in my work.

jiwhiz said...

I tested the simple web app with SpringSource dm Server 1.0.2.RELEASE and seems everything ok. Please try again with Updated Tutorial and let me know if you have problems.