I spent some time recently working on an web-application using spring and webwork. (<tangent>this combination created the core of one of the cleanest architectures I've worked with</tangent>). Someone asked how easy it might be to expose some functionality as a web service, so I thought I'd give it a go.
Grabbing a copy of Apache Axis was my first step. It's documentation guided me most of the way, but the only missing bit was how to get at a spring-created bean from an axis-aware class. Here's what I did.
After putting the required libraries (axis-ant.jar, axis.jar, commons-discovery.jar, commons-loggin.jar, jaxrpc.jar, wsdl4j.jar, saaj.jar) on the classpath, I had to declare all of the appropriate axis stuff in my web.xml file.
<web-app>
<listener>
<listener-class>org.apache.axis.transport.http.AxisHTTPSessionListener</listener-class>
</listener>
<servlet>
<servlet-name>axis</servlet-name>
<servlet-class>org.apache.axis.transport.http.AxisServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>axis</servlet-name>
<url-pattern>/services/*</url-pattern>
</servlet-mapping>
<mime-mapping>
<extension>wsdl</extension>
<mime-type>text/xml</mime-type>
</mime-mapping>
</web-app>
The next step was to create a class which would be exposed as a web service by Axis:
public class TodoItemWebService {
public String getTodoItemDescription(String title) {
return "dummy description";
}
}
To get the service to run, I also had to create a file named server-config.wsdd in the WEB-INF directory of my web application. I figured out what this looked like by going through the Axis tutorial which dynamically registers a service in your app. Statically creating the file works fine though too. Here's what mine looked like:
<?xml version="1.0" encoding="UTF-8"?>
<deployment xmlns="http://xml.apache.org/axis/wsdd/" xmlns:java="http://xml.apache.org/axis/wsdd/providers/java">
<handler name="LocalResponder" type="java:org.apache.axis.transport.local.LocalResponder"/>
<handler name="URLMapper" type="java:org.apache.axis.handlers.http.URLMapper"/>
<handler name="Authenticate" type="java:org.apache.axis.handlers.SimpleAuthenticationHandler"/>
<service name="items" provider="java:RPC" style="wrapped" use="literal">
<operation name="getTodoItemDescription" qname="ns1:getTodoList" returnQName="ns1:getTodoItemDescriptionResult"
returnType="xsd:string" soapAction="" xmlns:ns1="http://wrytradesman.com/" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<parameter qname="ns1:TodoItemTitle" type="xsd:string"/>
</operation>
<parameter name="allowedMethods" value="*"/>
<parameter name="className" value="com.wrytradesman.todolist.web.service.TodoItemWebService"/>
<parameter name="wsdlTargetNamespace" value="http://wrytradesman.com/"/>
</service>
<transport name="http">
<requestFlow>
<handler type="URLMapper"/>
<handler type="java:org.apache.axis.handlers.http.HTTPAuthHandler"/>
</requestFlow>
<parameter name="qs:list" value="org.apache.axis.transport.http.QSListHandler"/>
<parameter name="qs:wsdl" value="org.apache.axis.transport.http.QSWSDLHandler"/>
<parameter name="qs.list" value="org.apache.axis.transport.http.QSListHandler"/>
<parameter name="qs.method" value="org.apache.axis.transport.http.QSMethodHandler"/>
<parameter name="qs:method" value="org.apache.axis.transport.http.QSMethodHandler"/>
<parameter name="qs.wsdl" value="org.apache.axis.transport.http.QSWSDLHandler"/>
</transport>
<transport name="local">
<responseFlow>
<handler type="LocalResponder"/>
</responseFlow>
</transport>
</deployment>
The service definition in bold is what I had to write to get the service running. All of the surrounding info is setup stuff that is just needed to configure axis. At this stage of the game, I could deploy my web application and hit a url http://localhost//services/items?wsdl to get the WSDL definition for my service. In the space of about 5 minutes, a cow-orker had used that WSDL to create a .NET based client which called the service and got my hard-coded response.
With my web service now up and running, the only remaining problem was to create a "real" implementation that used one of my spring managed objects instead of a hard-coded response. The trick here is to get a reference to the application context first. Everything from that point is easy. The simplest path to that is get a reference to the servlet from the Axis message context, then use the servlet context to get the application context from spring. Then just call your spring bean as per normal. Here's what my final code looks like:
public class TodoItemWebService {
public String getTodoItemDescription(String title) {
HttpServlet servlet = (HttpServlet) MessageContext.getCurrentContext().getProperty(
HTTPConstants.MC_HTTP_SERVLET);
ApplicationContext context = WebApplicationContextUtils.getWebApplicationContext(servlet.getServletContext());
Map beans = context.getBeansOfType(TodoListRepository.class, false, false);
Iterator iterator = beans.values().iterator();
TodoListRepository repository = (TodoListRepository) iterator.next();
TodoItem item = repository.getTodoList().getItem(title);
return item.getDescription();
}
}
Thats it. Pretty straight forward really. There's a few corner cases to be covered off, but vertical slice is complete. The whole exercise took less than a days effort, which included learning about how Axis hangs together.
Posted by marty at December 14, 2004 10:42 AM [0 Trackbacks]
Comments
Another option is to extend org.springframework.remoting.jaxrpc.ServletEndpointSupport.
I'm using this to insert a level of indirection, where the Axis-registered service class delegates to a bean it retrieves from the application context.
import org.springframework.context.ApplicationContext;
import org.springframework.remoting.jaxrpc.ServletEndpointSupport;
public class JaxRpcVerzeichnisService extends ServletEndpointSupport
implements RemoteMyService {
private MyService _service;
protected void onInit() {
ApplicationContext ac = getWebApplicationContext();
assert ac != null : "no ApplicationContext available";
_service = (MyService)ac.getBean("myservice");
}
public Object myServiceMethod() {
assert _service != null : "_service not initialized";
return _service.myServiceMethod();
}
}
Posted by: Michael Schuerig at December 14, 2004 08:50 PM
THANK YOU! Man I started looking at this last Friday and was dreading the fight... you've made it easy. Thanks VERY VERY much!
R
Posted by: Robert S. Sfeir at December 15, 2004 01:24 AM
you might also take a look at:
http://opensource.atlassian.com/projects/spring/browse/SPR-371
Posted by: The VoodooChile at December 15, 2004 11:53 PM
Interessting options. It would be really helpful to have an official route documented in the Spring docs but i cant find any Webservice-Section at all.
The proposed url of "The VoodooChile" is quite promising though and i think i will take this route. But great blog on this topic, i appreciated the reading.
Marc
Posted by: Marc Logemann at January 27, 2005 01:09 AM
This code doesn't work- specifically
1. what's TodoItem?
2. what's TodoListRepository?
Appreciate your response.
Thx.
lkj
ublic class TodoItemWebService {
public String getTodoItemDescription(String title) {
HttpServlet servlet = (HttpServlet) MessageContext.getCurrentContext().getProperty(
HTTPConstants.MC_HTTP_SERVLET);
ApplicationContext context = WebApplicationContextUtils.getWebApplicationContext(servlet.getServletContext());
Map beans = context.getBeansOfType(TodoListRepository.class, false, false);
Iterator iterator = beans.values().iterator();
TodoListRepository repository = (TodoListRepository) iterator.next();
TodoItem item = repository.getTodoList().getItem(title);
return item.getDescription();
}
}
Posted by: lalit at January 27, 2005 09:49 AM
分享到:
相关推荐
Spring Web Services 官网 Spring Web Services API。 Spring Web Services 开发文档。
Marrying the two technologies is therefore a very natural choice.This book takes you through the design of RESTful web services and leverages the Spring Framework to implement these services....
Spring Web Services WS-Security示例 设置各种协议的样本 SOAP Web服务。 支持WS-Security的两种实现,即和 。 对于每种认证方法,每种认证方法都有一个不同的终结点: 不安全。 普通密码。 摘要密码。 签名...
webservices-api,webservices-extra,webservices-extra-api,webservices-rt,webservices-tools
Web services using java technology from sun
webservices-api webservices-extra webservices-extra-api webservices-rt webservices-tools
[Spring Web Services 2 Cookbook][Chapter-3][Testing-and-Monitoring-Web-Services]
NULL 博文链接:https://xiangxingchina.iteye.com/blog/762263
Developing-Restful-Web-Services-with-Jersey-2-0
在java开发services中,会用到: 1.webservices-api.jar 2.webservices-extra.jar 3.webservices-rt.jar 4.webservices-tools.jar 5.webservices-extra-api.jar 此压缩文件里就是这五个jar文件。
Accessing Web Services from a Visual Web Application
Spring Web Services (Spring-WS) is a product of the Spring community focused on creating document-driven Web services.
Database interaction using Spring and Hibernate/JPA- Spring Data JPA- Spring Data MongoDB- Messaging, emailing and caching support- Spring Web MVC- Developing RESTful web services using Spring Web ...
spring web services 2 cookbook spring web services 2 cookbook
webservices的开发图片和文档适合初学者
Spring web: Spring MVC, other dynamic scripting, integration with the popular Grails Framework (and Groovy), REST/web services, and more This book guides you step-by-step through topics using ...
Chapter 12 –Developing RESTful web services using Spring Web MVC Chapter 13 – More Spring Web MVC – internationalization, file upload and asynchronous request processing Chapter 14 – Securing ...
WebServices服务接口调用---基于rpc方式应用。sun-jaxws.xml方式
去几年,REST逐渐成为影响Web框架、Web协议与Web应用设计的重要概念。如果你还不了解REST,那这个简短的介绍将有助你快速掌握REST,此外还可以点击这里了解关于REST的更多信息。 相关厂商内容 高速下载:Adobe ...
spring-cloud-services-docs-1.0