Showing posts with label Web Application. Show all posts
Showing posts with label Web Application. Show all posts

Wednesday, March 25, 2009

Simple Web Application with SpringSource dm Server (Updated)

I posted my experience of developing web application on SpringSource dm Server, then struggled with Maven, OSGi for last several weeks, didn't know some people asked me questions about the Simple Web Application with SpringSource dm Server. I apologize for not setting comment notification.

So here is the updated tutorial:

1. Download and install Eclipse Ganymede SR2. Install Spring IDE 2.2.2 and dm Server Tools 1.1.2 from http://www.springsource.org/update/e3.4. Download and unzip SpringSource dm Server 1.0.2.RELEASE, and set up a server runtime in Eclipse at localhost.

2. Create a new SpringSource dm Server Bundle Project in Eclipse. Project name is "org.simple.web". Set Java source folder to src/main/java. Next, set symbolic name same as project name, the module type is "Web", and set target runtime to SpringSource dm Server. Next, web context path is "simple", and dispatcher servlet url pattern is "*.htm".

3. After project creation, move the META-INF folder from src/main/java 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. Add spring config files. Create folder src/main/resources/META-INF/spring, and add module-context.xml, osgi-context.xml.

src/main/resources/META-INF/spring/module-context.xml

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

 <context:component-scan base-package="org.simple.web"/>

 <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver" p:prefix="/WEB-INF/jsp/"
   p:suffix=".jsp"/>

</beans>

src/main/resources/META-INF/spring/osgi-context.xml

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

</beans:beans>

5. Create folder "src/main/resources/MODULE-INF", this is the folder for all the web content. Add index.html to MODULE-INF folder:

src/main/resources/MODULE-INF/index.html

<html>
<head>
  <meta http-equiv="Refresh" content="0; URL=home.htm">
</head>
</html>

The index.html redirects to home page "home.htm", and invoke Spring MVC code.

6. Add a very simple jsp file for the home page, just display welcome messag and list all members from backend:

src/main/resources/MODULE-INF/WEB-INF/jsp/home.jsp

<%@ 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>

7. Add Spring MVC controller class and support class for home page:

src/main/java/org/simple/web/HomePageController.java

package org.simple.web;

import java.util.ArrayList;
import java.util.List;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.servlet.ModelAndView;

@Controller
@RequestMapping("/home.htm")
public class HomePageController {
    public HomePageController() {
    }

    @RequestMapping(method = RequestMethod.GET)
    public ModelAndView handleRequest(HttpServletRequest request,
            HttpServletResponse response) throws Exception {
        List<Member> members = new ArrayList<Member>();
        members.add(new Member("Yuan Ji"));
        return new ModelAndView("home", "members", members);
    }
}

src/main/java/org/simple/web/Member.java

package org.simple.web;

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;
    }
}

8. Add org.simple.web project to SpringSource dm Server, and start the server. Open browser to http://localhost:8080 and click admin console. click /simple, you can see the home page of Open Toast Project.

Tuesday, January 13, 2009

Add Maven Support to dm Server Bundle Project

It took me several weekends to get maven working with my simple Web application.

My first approach was to use Apache Maven Eclipse Plugin, and add some tricks to work around its limitations. See my comments in Spring Forum dm Server Tooling and Maven: is it possible?

The issue is Maven Eclipse Plugin has not considered dm Server facet settings yet, so you have to manually add WTP project facet setting for dm Server in .settings\org.eclipse.wst.common.project.facet.core.xml file. There maybe some other ways to work around, but not neat.

Then I was thinking about extending its Mojo class org.apache.maven.plugin.eclipse.EclipsePlugin, and by adding additional project natures, build commands, etc. and we were done, just like M2EclipseMojo does. Although hadn't programmed Maven Plugin before, by reading tutorial and source code of Maven Eclipse Plugin, I thought it should be easy.

Setting up a plugin project is easy by following the Plugin Developer's document. Then I spent a whole morning struggling with NPE. First subclassed EclipsePlugin in my plugin project as S2DMEclipseMojo, and in the mojo, added dm Server related config for eclipse, similar to M2EclipseMojo. Theoretically it should work. But the project injected to the plugin was always null.

Tried all kinds of ways to figure out what's wrong, but no clue. Then started to search around in the Internet. Suddenly found this JIRA issue of Maven MPLUGIN-56 Inter-plugin Mojo inheritance. Hmm, Plexus should use JDK 5 annotation instead of javadoc annotation.

Anyway, the problem was found, so the dumb solution was to create a mojo class by copying code from EclipsePlugin and its superclass. After many tests and reviews, I found quite a lot of code is dealing with dependencies. Since we already use dm Server Tool to handle bundle dependency through MANIFEST.MF file, and we can use M2Eclipse plugin in Eclipse to handle unit test related dependencies like junit, easy mock, why not remove all those messy code? So a very simple mojo class was done and tested, seems it meets our needs. See the source code for S2DMEclipseMojo

This is my first Maven Plugin Project, very exciting. Then spent another weekend to get it released as 0.0.1, add documentation, publish to Google Code. It is very nice that we can use Google Code SVN service to publish our Web site and maven repository. See Open Toast Maven Plugin for SpringSource dm Server v0.0.1. The trick is you have to add svn property for all html files as "text/html" mime type. Maybe there is a easy way to do that, I don't know.

To use this plugin is very easy, simply by adding plugin repository in your project pom.xml, like:

 
  
  
   opentoast.maven.s2dm.plugin
   http://opentoastproject.googlecode.com/svn/mavenrepo
  
 

and then in your project root, type

mvn org.opentoast:maven-s2dm-plugin:0.0.1:eclipse

It will add Eclipse settings for the project, so you can import into Eclipse. Suppose you already set up your Eclipse with M2Eclipse and dm Server Tool plugins. You may have to run "Spring Tools - Refresh Bundle Dependencies" to get rid of compiler errors.

To use dm Server Tool with M2Eclipse, I apply another trick learned from Spring forum, that put all bundle dependencies to a profile, so M2Eclipse Plugin cannot find them.

The complete pom for my simple Web application is like this:



 4.0.0

 org.simple
 org.simple.web
 jar
 Simple Web Bundle
 0.0.1-SNAPSHOT

 
  
  3.2.2
  2.5.6.A
  1.1.2.A
  1.0.1
  1.5.0
  2.5.0
  2.1.0
  1.1.2
  4.5.0
  2.3.0
 

 
  
   bundle

   

    
    
     org.springframework
     org.springframework.beans
     
     ${spring.version}
     provided
    
    
     org.springframework
     org.springframework.core
     
     ${spring.version}
     provided
    
    
     org.springframework
     org.springframework.context
     
     ${spring.version}
     provided
    
    
     org.springframework
     org.springframework.context.support
     
     ${spring.version}
     provided
    
    
     org.springframework
     org.springframework.web
     
     ${spring.version}
     provided
    
    
     org.springframework
     org.springframework.web.servlet
     
     ${spring.version}
     provided
    

    
     javax.servlet
     com.springsource.javax.servlet
     
     ${servlet.version}
     provided
    

    
     javax.servlet
     com.springsource.javax.servlet.jsp
     
     ${jsp.version}
     provided
    

    
     org.apache.taglibs
     com.springsource.org.apache.taglibs.standard
     
     ${jstl.version}
     provided
    
   
  
 

 
   
   
    org.easymock
    com.springsource.org.easymock
    ${easymock.version}
    test
   
   
    org.junit
    com.springsource.org.junit
    ${junit.version}
    test
   

   
    org.springframework
    org.springframework.test
    ${spring.version}
    test
   
 
 
 
  
   
   
    org.apache.maven.plugins
    maven-compiler-plugin
    
     1.6
     1.6
    
   

   
    org.apache.maven.plugins
    maven-jar-plugin
    
     
      src/main/resources/META-INF/MANIFEST.MF
      
     
    
   

  
 
 
 
  
  
   opentoast.maven.s2dm.plugin
   http://opentoastproject.googlecode.com/svn/mavenrepo
  
 
 
 
    
   com.springsource.repository.bundles.release
   SpringSource Enterprise Bundle Repository - SpringSource Bundle Releases
   http://repository.springsource.com/maven/bundles/release
  
  
   com.springsource.repository.bundles.external
   SpringSource Enterprise Bundle Repository - External Bundle Releases
   http://repository.springsource.com/maven/bundles/external
  
  
 

See my post Simple Web Application with SpringSource dm Server for other details.

Next step is to focus on Open Toast Project again, and get the whole system running. One goal of open toast project is to set up infrastructure so I can work on business later or easily create new projects. However, it is too long to get infrastructure done, especially when using cutting edge technologies. But isn't it fun?

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.