Spring 3 RESTful Web Services

Step One – Project Creation with Maven

This tutorial is slightly different to my previous examples. In recent development I have begun to use Maven to manage my project dependencies.

If you are comfortable with creating a Web application project and Maven please skip down to the example code.

First of all you will need to install the Maven 2 plugin for Eclipse.

After you have installed the plugin create a new ‘Dynamic Web Project’ in Eclipse. Call it ‘SpringRestfulExample’.

Click Next. On the next screen we need to edit the src folder and the output folder. First of all remove the current src folder and then click ‘Add Folder…’

On the Add folder dialog enter the value /src/main/java and click OK.

Then make sure the default output folder reads target/classes. Click next

On the change the Context directory to read /src/main/webapp. Continue on to create the project.

Next we need to introduce Maven. Assuming you have installed the Maven plugin correctly Right click the Project and you should see a Maven menu item.

Highlight Maven and click ‘Enable Dependency Management’.

The next screen will ask you a few Maven options leave everything as it is apart from Packaging – change this to war. Click Finish.

Now we need to ensure the project uses any Maven dependencies we setup. Right click the Project and choose Properties.

From the Properties menu click ‘Java EE Module Dependencies’. On the right hand pane you will see ‘Maven Dependencies’ simply add a tick in that box and click Apply

Step Two – Making the Web application work

Next we’re going to make sure the web application works OK before we introduce Spring and other requirements.

In your src/main/webapp folder create a file called index.jsp and add some sample content like below:

<html>
	<head>
		<title>Spring RESTful Example</title>
	</head>
	<body>
		<p>Your WebApplication is up and running....</p>
	</body>
</html>

(If you open your web.xml file you’ll see a list of welcome files we’re creating the index.jsp of that welcome file list)

I’ll assume you’re comfortable with setting up local servers in Eclipse. If you open up your Servers view in Eclipse and add your project to your server, then start you server. You should be able to visit http://localhost:8080/SpringRestfulExample/ and view the page you created.

Step Three – Introducing Spring

In the root of your project you’ll notice that there is a file called pom.xml – this manages all your Maven dependencies.

Open the file (choose the tab pom.xml in the editor if the file opens up in the Maven editor) and add the following content:

<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>SpringRestfulExample</groupId>
	<artifactId>SpringRestfulExample</artifactId>
	<packaging>war</packaging>
	<version>0.0.1-SNAPSHOT</version>
 
 	<properties>
    	<org.springframework.version>3.0.0.RELEASE</org.springframework.version>
	</properties>
 	<build>
 		<defaultGoal>compile</defaultGoal>
 		<directory>target</directory>
 		<sourceDirectory>src/main/java</sourceDirectory>
 		<outputDirectory>target/classes</outputDirectory>
 	</build>
 
	<dependencies>
		<dependency>
			<groupId>org.springframework</groupId>
		  	<artifactId>spring-core</artifactId>
		  	<version>${org.springframework.version}</version>
		</dependency>
		<dependency>
	  		<groupId>org.springframework</groupId>
	  		<artifactId>spring-expression</artifactId>
	  		<version>${org.springframework.version}</version>
		</dependency>
		<dependency>
  			<groupId>org.springframework</groupId>
  			<artifactId>spring-beans</artifactId>
  			<version>${org.springframework.version}</version>
		</dependency>
		<dependency>
  			<groupId>org.springframework</groupId>
  			<artifactId>spring-aop</artifactId>
  			<version>${org.springframework.version}</version>
		</dependency>
		<dependency>
  			<groupId>org.springframework</groupId>
  			<artifactId>spring-context</artifactId>
  			<version>${org.springframework.version}</version>
		</dependency>
		<dependency>
  			<groupId>org.springframework</groupId>
  			<artifactId>spring-context-support</artifactId>
  			<version>${org.springframework.version}</version>
		</dependency>
		<dependency>
  			<groupId>org.springframework</groupId>
  			<artifactId>spring-web</artifactId>
  			<version>${org.springframework.version}</version>
		</dependency>
		<dependency>
  			<groupId>org.springframework</groupId>
  			<artifactId>spring-webmvc</artifactId>
  			<version>${org.springframework.version}</version>
		</dependency>
		<dependency>
  			<groupId>org.springframework</groupId>
  			<artifactId>spring-oxm</artifactId>
  			<version>${org.springframework.version}</version>
		</dependency>
		<dependency>
			<groupId>org.slf4j</groupId>
			<artifactId>slf4j-log4j12</artifactId>
			<version>1.4.2</version>
		</dependency>
		<dependency>
			<groupId>org.apache.tiles</groupId>
			<artifactId>tiles-api</artifactId>
			<version>2.1.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-jsp</artifactId>
			<version>2.1.2</version>
		</dependency>
		<dependency>
			<groupId>javax.servlet</groupId>
			<artifactId>jstl</artifactId>
			<version>1.1.2</version>
		</dependency>
		<dependency>
			<groupId>taglibs</groupId>
			<artifactId>standard</artifactId>
			<version>1.1.2</version>
		</dependency>
 
	</dependencies>
 
</project>

This Maven configuration includes all the required elements for the Spring example we’re going to be working with. If you need to read up more on Maven and Spring please see the SpringSource recent blog post.

Step Four – Configuring Spring MVC

Although we’re going to make an application that serves up RESTful XML we need to integrate Spring Web MVC. First of all we’ll create some basic Pojo objects that we shall represent.

Right click the src/main/java folder and create a new package called ‘com.spring.datasource’

Within that package create a new class called ‘Student’. Add the following content:

package com.spring.datasource;
 
/**
 * @author Eggsy - eggsy_at_eggsylife.co.uk
 *
 */
public class Student {
	private int id = -1;
	private String name = null;
 
	public Student() {
 
	}
 
	public Student(int id, String name) {
		this.id = id;
		this.name = name;
	}
 
	/**
	 * @return the id
	 */
	public int getId() {
		return id;
	}
	/**
	 * @param id the id to set
	 */
	public void setId(int id) {
		this.id = id;
	}
	/**
	 * @return the name
	 */
	public String getName() {
		return name;
	}
	/**
	 * @param name the name to set
	 */
	public void setName(String name) {
		this.name = name;
	}
}

In the same package create a class called ‘Classroom’ and add the following:

package com.spring.datasource;
 
import java.util.ArrayList;
 
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
 
/**
 * @author Eggsy - eggsy_at_eggsylife.co.uk
 *
 */
@XmlRootElement(name = "class")
public class Classroom {
 
	private String classId = null;
	private ArrayList<Student> students = null;
 
	public Classroom() {
 
	}
 
	public Classroom(String id) {
		this.classId = id;
		students = new ArrayList<Student>();
		Student studentOne = new Student(1, "Student One");
		Student studentTwo = new Student(2, "Student Two");
		students.add(studentOne);
		students.add(studentTwo);
	}
 
	/**
	 * @return the classId
	 */
	public String getClassId() {
		return classId;
	}
 
	/**
	 * @param classId the classId to set
	 */
	public void setClassId(String classId) {
		this.classId = classId;
	}
 
	/**
	 * @return the students
	 */
	@XmlElement(name="student")
	public ArrayList<Student> getStudents() {
		return students;
	}
 
	/**
	 * @param students the students to set
	 */
	public void setStudents(ArrayList<Student> students) {
		this.students = students;
	}
}

A classroom is just a collection of students – in this example I have hard coded two students but you can imagine that this may be a datasource. Also note the further use of the @XmlElement annotations.

Now create a new package called ‘com.spring.controller’.

This will contain our Spring MVC controller. Within that package create a new class called ‘StudentsController’ and add the following:

package com.spring.controller;
 
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;
 
import com.spring.datasource.Classroom;
 
/**
 * @author Eggsy - eggsy_at_eggsylife.co.uk
 *
 */
@Controller
public class StudentsController {
 
	public static final String STUDENTS_VIEW_KEY = "studentsView";
 
	@RequestMapping(method=RequestMethod.GET,value="/students")
	public ModelAndView showStudentsPage() {
		Classroom classOfStudents = new Classroom("Class One");
		ModelAndView mav = new ModelAndView(STUDENTS_VIEW_KEY);
		mav.addObject("classRoom", classOfStudents);
		return mav;
	}
}

I’ll assume you are comfortable with the Spring controller annotations. If not you can have a quick lookover my previous Spring blog posts. We use the same controlller for REST requests as well as normal HTML requests. Also as you can see we always return the same view. In essence the controller doesn’t do anything special or anything different from previous controllers you may have written.

It is within the servlet.xml file configuration that takes over handling the REST requests.

<bean id="studentsView" class="org.springframework.web.servlet.view.xml.MarshallingView">
	<constructor-arg ref="jaxbMarshaller" />
</bean>
 
<!-- JAXB2 marshaller. Automagically turns beans into xml -->
<bean id="jaxbMarshaller" class="org.springframework.oxm.jaxb.Jaxb2Marshaller">
	<property name="classesToBeBound">
		<list>
			<value>com.spring.datasource.Classroom</value>
			<value>com.spring.datasource.Student</value>
		</list>
	</property>
</bean>

Notice name a bean studentsView which is a Spring Mashalling view. This matches the view our controller returns. We then make use of another great Spring feature called the ContentNegotiatingViewResolver this bean allows us to handle XML requests and HTML requests and it basically makes decision on which view resolver to use. The bean is declared like so:

<bean class="org.springframework.web.servlet.view.ContentNegotiatingViewResolver">
	<property name="mediaTypes">
	    <map>
	        <entry key="xml" value="application/xml"/>
	        <entry key="html" value="text/html"/>
	    </map>
	</property>
	<property name="viewResolvers">
	    <list>
	        <bean class="org.springframework.web.servlet.view.BeanNameViewResolver"/>
	        <bean class="org.springframework.web.servlet.view.UrlBasedViewResolver">
			<property name="viewClass" value="org.springframework.web.servlet.view.tiles2.TilesView"/>
		</bean>
	    </list>
	</property>
</bean>

The content resolver declares two media types that we can handle (You can add more such as JSON) and then for the two media types we declare two View resolvers. For XML requests we use the BeanNameViewResolver so in practice we use the studentsView bean discussed earlier. Then for normal HTML requests we use the standard UrlBasedViewResolver configured with Tiles2 defintions.

The complete file is as shown below:

<?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:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="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">
 
 
	<context:component-scan base-package="com.spring.controller" />
	<bean class="org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping"/>
	<bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter"/>
 
	<bean id="tilesConfigurer" class="org.springframework.web.servlet.view.tiles2.TilesConfigurer">
		<property name="definitions">
			<list>
      				<value>/WEB-INF/tiles-defs/templates.xml</value>
    			</list>
		</property>
	</bean>
 
	<bean id="studentsView" class="org.springframework.web.servlet.view.xml.MarshallingView">
		<constructor-arg ref="jaxbMarshaller" />
	</bean>
 
	<!-- JAXB2 marshaller. Automagically turns beans into xml -->
	<bean id="jaxbMarshaller" class="org.springframework.oxm.jaxb.Jaxb2Marshaller">
		<property name="classesToBeBound">
			<list>
				<value>com.spring.datasource.Classroom</value>
				<value>com.spring.datasource.Student</value>
			</list>
		</property>
	</bean>
 
	<bean class="org.springframework.web.servlet.view.ContentNegotiatingViewResolver">
        	<property name="mediaTypes">
            		<map>
                		<entry key="xml" value="application/xml"/>
				<entry key="html" value="text/html"/>
            		</map>
		</property>
        	<property name="viewResolvers">
            		<list>
		                <bean class="org.springframework.web.servlet.view.BeanNameViewResolver"/>
                		<bean class="org.springframework.web.servlet.view.UrlBasedViewResolver">
					<property name="viewClass" value="org.springframework.web.servlet.view.tiles2.TilesView"/>
				</bean>
            		</list>
       		</property>
    	</bean>
</beans>

To complete the application we should create the required JSP’s and Tiles configuration. Under the /src/main/webapp create a new folder called ‘pages’ and create a file named ‘students.jsp’ within it. Add the following content:

<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<p>Classroom of students</p>
 
<c:forEach var="student" items="${classRoom.students}">
	${student.id} - ${student.name}<br/>
</c:forEach>

Finally we need to create the tiles defintion file the view. Create a new folder called ’tiles-defs’ in the WEB-INF folder and create a file called ‘templates.xml’ within it. (Notice this matches the location in our servlet.xml file

Add the following content to the templates.xml file:

<?xml version="1.0" encoding="ISO-8859-1" ?>
<!DOCTYPE tiles-definitions PUBLIC
       "-//Apache Software Foundation//DTD Tiles Configuration 2.0//EN"
       "http://tiles.apache.org/dtds/tiles-config_2_0.dtd">
 
<tiles-definitions>
 
	<definition name="studentsView" template="/pages/students.jsp">
	</definition>
 
</tiles-definitions>

Step Five – Updating the web.xml

Finally we need to configure the web.xml to work with Spring Web MVC. Open your web.xml file (located in the webapp folder) and make sure it matches the following:

<?xml version="1.0" encoding="UTF-8"?>
<web-app id="WebApp_ID" version="2.4" xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
	<display-name>SpringRestfulExample</display-name>
 
 
	<servlet>
		<servlet-name>SpringRestfulExample</servlet-name>
		<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
		<load-on-startup>1</load-on-startup>
	</servlet>
 
	<servlet-mapping>
    		<servlet-name>SpringRestfulExample</servlet-name>
    		<url-pattern>/app/*</url-pattern>
	</servlet-mapping>
 
	<welcome-file-list>
		<welcome-file>index.jsp</welcome-file>
	</welcome-file-list>
</web-app>

That should just about be it. If you start your webserver and visit the page http://localhost:8080/SpringRestfulExample/app/students you should see the JSP page you created with the two students listed.

However if you perform a curl request (mocking an XML request) you should see the XML representation of the classroom:

curl -H 'Accept: application/xml' http://localhost:8080/SpringRestfulExample/app/students

Project download

I have made the project available for download on Google’s Project hosting. You can get hold of it at http://code.google.com/p/eggsy-spring3-restful-example/ or via SVN on the URL http://eggsy-spring3-restful-example.googlecode.com/svn/trunk/

Resources

Spring forum post and help from user Toxic: http://forum.springsource.org/showthread.php?t=82146

REST in Spring 3 – Spring source blog : http://blog.springsource.com/2009/03/08/rest-in-spring-3-mvc/

Eyal Lupu’s Java Blog : http://www.jroller.com/eyallupu/entry/content_negotiation_using_spring_mvc

SpringSource.org – RESTful Services : http://static.springsource.org/spring/docs/3.0.0.M3/spring-framework-reference/html/ch18s02.html

14 thoughts on “Spring 3 RESTful Web Services

  1. Hi there

    Assuming you are using Restful URL’s in that the URL identified a particular resource which users have/haven’t got access to I would look into Spring Security and in particular the Spring ACL framework.

    This allows use to restrict access based upon the item being accessed. For example you might have a system where users belong to accounts and you wish that they can only access URL’s for their accounts. Spring ACL would be able to address this.

    James

  2. How would you suggest to secure services? I was thinking to use basic http auth on SSL, but I am not much familiar with Spring Architecture. Any suggestions?

  3. [10/4/11 11:42:24:796 EDT] 0000002a DispatcherSer E org.springframework.web.servlet.FrameworkServlet initServletBean Context initialization failed
    org.springframework.beans.factory.BeanCreationException: Error creating bean with name ‘studentsView’ defined in ServletContext resource [/WEB-INF/student-servlet.xml]: Cannot resolve reference to bean ‘jaxbMarshaller’ while setting constructor argument; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name ‘jaxbMarshaller’ defined in ServletContext resource [/WEB-INF/student-servlet.xml]: Initialization of bean failed; nested exception is org.springframework.beans.TypeMismatchException: Failed to convert property value of type ‘java.util.ArrayList’ to required type ‘java.lang.Class[]’ for property ‘classesToBeBound’; nested exception is java.lang.IllegalArgumentException: Error loading class [datasource.Classroom]: problem with class file or dependent class.
    at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveReference(BeanDefinitionValueResolver.java:328)
    at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveValueIfNecessary(BeanDefinitionValueResolver.java:106)
    at org.springframework.beans.factory.support.ConstructorResolver.resolveConstructorArguments(ConstructorResolver.java:600)
    at org.springframework.beans.factory.support.ConstructorResolver.autowireConstructor(ConstructorResolver.java:140)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.autowireConstructor(AbstractAutowireCapableBeanFactory.java:984)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:886)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:479)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:450)
    at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:290)
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:222)
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:287)
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:189)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:557)
    at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:842)
    at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:416)
    at org.springframework.web.servlet.FrameworkServlet.createWebApplicationContext(FrameworkServlet.java:443)
    at org.springframework.web.servlet.FrameworkServlet.createWebApplicationContext(FrameworkServlet.java:459)
    at org.springframework.web.servlet.FrameworkServlet.initWebApplicationContext(FrameworkServlet.java:340)
    at org.springframework.web.servlet.FrameworkServlet.initServletBean(FrameworkServlet.java:307)
    at org.springframework.web.servlet.HttpServletBean.init(HttpServletBean.java:127)
    at javax.servlet.GenericServlet.init(GenericServlet.java:256)
    at com.ibm.ws.webcontainer.servlet.ServletWrapper.init(ServletWrapper.java:235)
    at com.ibm.ws.wswebcontainer.servlet.ServletWrapper.init(ServletWrapper.java:342)
    at com.ibm.ws.webcontainer.servlet.ServletWrapper.initialize(ServletWrapper.java:1375)
    at com.ibm.ws.wswebcontainer.servlet.ServletWrapper.initialize(ServletWrapper.java:175)
    at com.ibm.wsspi.webcontainer.extension.WebExtensionProcessor.createServletWrapper(WebExtensionProcessor.java:99)
    at com.ibm.ws.webcontainer.webapp.WebApp.getServletWrapper(WebApp.java:910)
    at com.ibm.ws.webcontainer.webapp.WebApp.getServletWrapper(WebApp.java:832)
    at com.ibm.ws.webcontainer.webapp.WebApp.initializeTargetMappings(WebApp.java:550)
    at com.ibm.ws.webcontainer.webapp.WebApp.commonInitializationFinish(WebApp.java:387)
    at com.ibm.ws.wswebcontainer.webapp.WebApp.initialize(WebApp.java:293)
    at com.ibm.ws.wswebcontainer.webapp.WebGroup.addWebApplication(WebGroup.java:93)
    at com.ibm.ws.wswebcontainer.VirtualHost.addWebApplication(VirtualHost.java:162)
    at com.ibm.ws.wswebcontainer.WebContainer.addWebApp(WebContainer.java:673)
    at com.ibm.ws.wswebcontainer.WebContainer.addWebApplication(WebContainer.java:626)
    at com.ibm.ws.webcontainer.component.WebContainerImpl.install(WebContainerImpl.java:335)
    at com.ibm.ws.webcontainer.component.WebContainerImpl.start(WebContainerImpl.java:551)
    at com.ibm.ws.runtime.component.ApplicationMgrImpl.start(ApplicationMgrImpl.java:1274)
    at com.ibm.ws.runtime.component.DeployedApplicationImpl.fireDeployedObjectStart(DeployedApplicationImpl.java:1137)
    at com.ibm.ws.runtime.component.DeployedModuleImpl.start(DeployedModuleImpl.java:573)
    at com.ibm.ws.runtime.component.DeployedApplicationImpl.start(DeployedApplicationImpl.java:816)
    at com.ibm.ws.runtime.component.ApplicationMgrImpl.startApplication(ApplicationMgrImpl.java:945)
    at com.ibm.ws.runtime.component.ApplicationMgrImpl$1.run(ApplicationMgrImpl.java:1461)
    at com.ibm.ws.security.auth.ContextManagerImpl.runAs(ContextManagerImpl.java:4251)
    at com.ibm.ws.security.auth.ContextManagerImpl.runAsSystem(ContextManagerImpl.java:4348)
    at com.ibm.ws.security.core.SecurityContext.runAsSystem(SecurityContext.java:245)
    at com.ibm.ws.runtime.component.ApplicationMgrImpl.startApplication(ApplicationMgrImpl.java:1466)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:79)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:618)
    at sun.reflect.misc.Trampoline.invoke(MethodUtil.java:68)
    at sun.reflect.GeneratedMethodAccessor33.invoke(Unknown Source)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:618)
    at sun.reflect.misc.MethodUtil.invoke(MethodUtil.java:271)
    at javax.management.modelmbean.RequiredModelMBean.invokeMethod(RequiredModelMBean.java:1092)
    at javax.management.modelmbean.RequiredModelMBean.invoke(RequiredModelMBean.java:973)
    at com.sun.jmx.mbeanserver.DynamicMetaDataImpl.invoke(DynamicMetaDataImpl.java:231)
    at com.sun.jmx.mbeanserver.MetaDataImpl.invoke(MetaDataImpl.java:238)
    at com.sun.jmx.interceptor.DefaultMBeanServerInterceptor.invoke(DefaultMBeanServerInterceptor.java:833)
    at com.sun.jmx.mbeanserver.JmxMBeanServer.invoke(JmxMBeanServer.java:802)
    at com.ibm.ws.management.AdminServiceImpl$1.run(AdminServiceImpl.java:1139)
    at com.ibm.ws.security.util.AccessController.doPrivileged(AccessController.java:118)
    at com.ibm.ws.management.AdminServiceImpl.invoke(AdminServiceImpl.java:1032)
    at com.ibm.ws.management.commands.AdminServiceCommands$InvokeCmd.execute(AdminServiceCommands.java:251)
    at com.ibm.ws.console.core.mbean.MBeanHelper.invoke(MBeanHelper.java:239)
    at com.ibm.ws.console.appdeployment.ApplicationDeploymentCollectionAction.execute(ApplicationDeploymentCollectionAction.java:544)
    at org.apache.struts.action.RequestProcessor.processActionPerform(Unknown Source)
    at org.apache.struts.action.RequestProcessor.process(Unknown Source)
    at org.apache.struts.action.ActionServlet.process(Unknown Source)
    at org.apache.struts.action.ActionServlet.doPost(Unknown Source)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:763)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:856)
    at com.ibm.ws.webcontainer.servlet.ServletWrapper.service(ServletWrapper.java:1213)
    at com.ibm.ws.webcontainer.servlet.ServletWrapper.service(ServletWrapper.java:1154)
    at com.ibm.ws.webcontainer.filter.WebAppFilterChain.doFilter(WebAppFilterChain.java:118)
    at com.ibm.ws.webcontainer.filter.WebAppFilterChain._doFilter(WebAppFilterChain.java:87)
    at com.ibm.ws.webcontainer.filter.WebAppFilterManager.doFilter(WebAppFilterManager.java:848)
    at com.ibm.ws.webcontainer.filter.WebAppFilterManager.doFilter(WebAppFilterManager.java:691)
    at com.ibm.ws.webcontainer.servlet.ServletWrapper.handleRequest(ServletWrapper.java:654)
    at com.ibm.ws.wswebcontainer.servlet.ServletWrapper.handleRequest(ServletWrapper.java:526)
    at com.ibm.ws.webcontainer.webapp.WebAppRequestDispatcher.forward(WebAppRequestDispatcher.java:325)
    at org.apache.struts.action.RequestProcessor.doForward(Unknown Source)
    at org.apache.struts.tiles.TilesRequestProcessor.doForward(Unknown Source)
    at org.apache.struts.action.RequestProcessor.processForwardConfig(Unknown Source)
    at org.apache.struts.tiles.TilesRequestProcessor.processForwardConfig(Unknown Source)
    at com.ibm.isclite.container.controller.InformationController.processForwardConfig(InformationController.java:214)
    at org.apache.struts.action.RequestProcessor.process(Unknown Source)
    at org.apache.struts.action.ActionServlet.process(Unknown Source)
    at org.apache.struts.action.ActionServlet.doPost(Unknown Source)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:763)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:856)
    at com.ibm.ws.webcontainer.servlet.ServletWrapper.service(ServletWrapper.java:1213)
    at com.ibm.ws.webcontainer.servlet.ServletWrapper.service(ServletWrapper.java:1154)
    at com.ibm.ws.webcontainer.filter.WebAppFilterChain.doFilter(WebAppFilterChain.java:145)
    at com.ibm.ws.console.core.servlet.WSCUrlFilter.setUpCommandAssistence(WSCUrlFilter.java:792)
    at com.ibm.ws.console.core.servlet.WSCUrlFilter.continueStoringTaskState(WSCUrlFilter.java:363)
    at com.ibm.ws.console.core.servlet.WSCUrlFilter.doFilter(WSCUrlFilter.java:229)
    at com.ibm.ws.webcontainer.filter.FilterInstanceWrapper.doFilter(FilterInstanceWrapper.java:190)
    at com.ibm.ws.webcontainer.filter.WebAppFilterChain.doFilter(WebAppFilterChain.java:130)
    at com.ibm.ws.webcontainer.filter.WebAppFilterChain._doFilter(WebAppFilterChain.java:87)
    at com.ibm.ws.webcontainer.filter.WebAppFilterManager.doFilter(WebAppFilterManager.java:848)
    at com.ibm.ws.webcontainer.filter.WebAppFilterManager.doFilter(WebAppFilterManager.java:691)
    at com.ibm.ws.webcontainer.servlet.ServletWrapper.handleRequest(ServletWrapper.java:654)
    at com.ibm.ws.wswebcontainer.servlet.ServletWrapper.handleRequest(ServletWrapper.java:526)
    at com.ibm.ws.webcontainer.servlet.CacheServletWrapper.handleRequest(CacheServletWrapper.java:90)
    at com.ibm.ws.webcontainer.WebContainer.handleRequest(WebContainer.java:764)
    at com.ibm.ws.wswebcontainer.WebContainer.handleRequest(WebContainer.java:1478)
    at com.ibm.ws.webcontainer.channel.WCChannelLink.ready(WCChannelLink.java:133)
    at com.ibm.ws.http.channel.inbound.impl.HttpInboundLink.handleDiscrimination(HttpInboundLink.java:457)
    at com.ibm.ws.http.channel.inbound.impl.HttpInboundLink.handleNewRequest(HttpInboundLink.java:515)
    at com.ibm.ws.http.channel.inbound.impl.HttpInboundLink.processRequest(HttpInboundLink.java:300)
    at com.ibm.ws.http.channel.inbound.impl.HttpICLReadCallback.complete(HttpICLReadCallback.java:102)
    at com.ibm.ws.ssl.channel.impl.SSLReadServiceContext$SSLReadCompletedCallback.complete(SSLReadServiceContext.java:1830)
    at com.ibm.ws.tcp.channel.impl.AioReadCompletionListener.futureCompleted(AioReadCompletionListener.java:165)
    at com.ibm.io.async.AbstractAsyncFuture.invokeCallback(AbstractAsyncFuture.java:217)
    at com.ibm.io.async.AsyncChannelFuture.fireCompletionActions(AsyncChannelFuture.java:161)
    at com.ibm.io.async.AsyncFuture.completed(AsyncFuture.java:136)
    at com.ibm.io.async.ResultHandler.complete(ResultHandler.java:196)
    at com.ibm.io.async.ResultHandler.runEventProcessingLoop(ResultHandler.java:751)
    at com.ibm.io.async.ResultHandler$2.run(ResultHandler.java:881)
    at com.ibm.ws.util.ThreadPool$Worker.run(ThreadPool.java:1551)

  4. @Stephen

    In that case you could simply write to the response stream and set the response type like so:

    @RequestMapping(method=RequestMethod.GET)
    public void myControllerMethod( HttpServletResponse response) {
    PrintWriter out = response.getWriter();
    out.println(yourXMLHere);
    response.setContentType("application/xml");
    out.close();
    }

    The HttpServletResponse object is another parameter Spring request mapped methods can use within their signature.

    Would that help?

    Eggsy

  5. Yes, the requirement is to Post/Put xml to the controller and return xml as the response body. The StringHttpMessageConverter would work fine to extract the posted xml. Then I just need to return a simple xml back in the response body that is where I am stuck. I do not need the Jaxb2Marshaller because I do not have an object unmarshall.

  6. This is so very cool. Works like a charm. Same url can serve both html/text and xml/text.
    Question if I have a service which generates xml already, what viewResolver I should use instead of the MarshallingView?

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>