问题
I'm in a difficult position: We have a 3rd party enterprise system that exposes a Java-based API. However, we are a 100% .Net oriented development team. Essentially, I need to wrap the Java API with something that C# code can call.
Web services would be great, but the only Java application server supported on our infrastructure is WebSphere 6.1. This means the ancient (and deprecated) JAX-RPC web service framework is the only way for us to expose web services. Just getting a simple proof-of-concept working here has been a nightmare (because of Java inexperience, WebSphere being awful, JAX-RPC being clunky, and lots of JAR hell).
The new JAX-WS 2.0 web service framework in JAVA EE 5 looks great-- is there any way to run this without an entire Java application server? For example, in .Net's WCF (Windows Communication Framework), you can host services pretty much anywhere you want (in-process, Windows Service, IIS 6/7 etc).
What is the most lightweight way to wrap this library with some web services?
回答1:
Yes.
If you can create a Java method which is 1) annotated with @WebMetod and 2) takes the needed parameters and call into your 3'rd party code, and wrap it up as a web application you can use the Metro stack - https://metro.dev.java.net/ - with any Servlet 2.5 web container (put it in the web containers global lib folder) to expose the above method as a web service. We are using an embedded Jetty, but I've verified this works with Tomcat.
I wrote up my findings in http://archive.midrange.com/java400-l/200904/msg00071.html
I downloaded Metro 1.4 from https://metro.dev.java.net/1.4/ (version 1.5 is very new and I haven't looked at it), which eventually unpacks to several jar files.
Copy webservices-api.jar, webservices-rt.jar, webservices-extra-api.jar and webservices-extra.jar (four files) to the folder containing "blessed" jarfiles common to all of tomcat - I believe it is ${TOMCAT}/lib for Tomcat 6.[1]
In your Eclipse project eventually ending up to be a WAR file:
If your workspace JRE is Java 5, you must add webservices-api.jar to the classpath (it should not be deployed in the end). If it is Java 6 you should be able to skip this step.
Create a class foo.Ping looking like:
package foo;
import java.net.InetAddress;
import java.net.UnknownHostException;
/**
Ping is a simple web service class providing a "yes, we have contact" class.
Currently the doPing() method provides a response with the host name and
address (if available) and the current server time.
*/
@javax.jws.WebService
public class Ping {
@javax.jws.WebMethod(action = "doPing")
public String doPing() {
System.out.println("Ping.doPing() called.");
String hostName;
try {
hostName = InetAddress.getLocalHost().getHostName();
} catch (UnknownHostException e) {
hostName = "unknown (" + e.getMessage() + ")";
}
String hostAddress;
try {
hostAddress = InetAddress.getLocalHost().getHostAddress();
} catch (UnknownHostException e) {
hostAddress = "unknown (" + e.getMessage() + ")";
}
return "Reached '" + hostName + "' (" + hostAddress + ") at "
+ new java.util.Date() + " java.version="
+ System.getProperty("java.version", "(not set)");
}
}
- In your WEB-INF/web.xml add this snippet:
<listener> <listener-class>com.sun.xml.ws.transport.http.servlet.WSServletContextListener</listener-class> </listener> <servlet> <description>JAX-WS endpoint - this servlet must handle all endpoints</description> <display-name>webservice</display-name> <servlet-name>webservice</servlet-name> <servlet-class>com.sun.xml.ws.transport.http.servlet.WSServlet</servlet-class> <load-on-startup>1</load-on-startup> </servlet> <!-- each endpoint must have a mapping to the JAX-WS endpoint servlet --> <servlet-mapping> <servlet-name>webservice</servlet-name> <url-pattern>/ws</url-pattern> </servlet-mapping>
- Create a NEW file WEB-INF/sun-jaxws.xml:
<endpoints xmlns='http://java.sun.com/xml/ns/jax-ws/ri/runtime' version='2.0'> <endpoint name='ping' implementation='foo.Ping'url-pattern='/ws'> </endpoint </endpoints>
Ensure that both web.xml and sun-jaxws.xml are included in the deployment!
Done!
Now deploy your war file to the Tomcat prepared above, and open "/ws" under your deployed web application. This might be http://localhost:8080/foo/ws
;. This will give you a page with information including a link to WSDL for all web services, including the Ping. This link can be used directly in any WSDL processing tool, including the web service tool in Eclipse IDE for Java EE Developers and WSDCi.
Hope this helps you :)
[1] Not making them global WILL give you classloader problems!
回答2:
I don't quite understand your statement "the only Java application server supported on our infrastructure is WebSphere 6.1" with respect to the question about how to run other stuff. But no, you don't need a full App Server just to expose a web service.
I think this is a good starting point for you: http://docs.codehaus.org/display/JETTY/J2se6HttpServerSPI
回答3:
Since you can't update your version of the JDK, as I expect you are tied to what WebSphere needs, you may want to look at trying the axis famework, from apache.
This would require you to write a webservice that would just pass calls to the java code, but it should provide you the tools to get online, and it works well with older versions of java.
I expect that Jax-WS would be a problem unless by some miracle you are on JDK5 at least, then JAX-WS would be helpful, as the annotations makes the development more like the webservice model under .NET 2.0.
回答4:
I ended up finding a solution that was far easier than any of the above. We created some simple classes (like the doPing() method in @Thorbjørn Ravn Andersen's answer) with the @javax.jws.WebService
and @javax.jws.WebMethod
annotations, then deployed them using:
string url = "http://localhost:8282/MyService"
MyService serviceInstance = new MyService();
Endpoint svc = Endpoint.publish(url, serviceInstance);
I was then able to point Visual Studio at http://localhost:8282/MyService?wsdl
and generate a client. Easy as pie.
We have run a lot of requests through this service over a large span of time and have not noticed any problems. We wrapped this with the Java Service Wrapper so that it comes back up across reboots/JVM crashes, etc. A poor man's application server.
I hope this might help any other .NET developer looking to interoperate with Java without having to remap your brain to do it.
来源:https://stackoverflow.com/questions/1703951/interoperate-between-c-sharp-and-java-using-web-services-without-a-java-ee-appli