In-process SOAP service server for Java - java

OK, I am developing a program which will be deployed to lots of machines (Windows, Linux, AIX, z/Linux, openVMS, etc.). I want that application to contain a SOAP web service, but I don't want to bundle tomcat or run a separate service for the services (I want them in the same process as the rest of the application).
Basically what I'm looking for is something where I can define a class (say WebServices). I'm OK with writing WSDL or any other kind of service description as well. The I want something like this:
SOAPServer server = makeMeASoapServer();
//do config on the server
server.add(new WebService(...));
server.listen(port);
Obviously the names and parameters will be different.
I've been looking at Axis, and it seems like it provides this, but I don't know what classes I need to use. Am I crazy in wanting this kind of behavior? I can't believe more people aren't looking for this, I do this all the time with embedded web services within .NET clients.

Seems jdk 6.0 already comes with a jax-ws implementation, and a little server you can embed.
I havn't figured out all the pieces but here's a start:
mkdir -p helloservice/endpoint/
helloservice/endpoint/Hello.java :
package helloservice.endpoint;
import javax.jws.WebService;
#WebService()
public class Hello {
private String message = new String("Hello, ");
public void Hello() {}
public String sayHello(String name) {
return message + name + ".";
}
}
helloservice/endpoint/Server.java:
package helloservice.endpoint;
import javax.xml.ws.Endpoint;
public class Server {
protected Server() throws Exception {
System.out.println("Starting Server");
Object implementor = new Hello();
String address = "http://localhost:9000/SoapContext/SoapPort";
Endpoint.publish(address, implementor);
}
public static void main(String args[]) throws Exception {
new Server();
System.out.println("Server ready...");
Thread.sleep(5 * 60 * 1000);
System.out.println("Server exiting");
System.exit(0);
}
}
Build the thing:
mkdir build
javac -d build helloservice/endpoint/*java
$JAVA_HOME/wsgen -d build -s build -classpath . helloservice.endpoint.Hello
Run the thing:
java -cp build helloservice.endpoint.Server
Somethings running on http://localhost:9000/SoapContext/SoapPort now.
You can get the wsdl on http://localhost:9000/SoapContext/SoapPort?WSDL
Havn't gotten around to making a client yet..

In addition to nos's great answer, I found a class in Apache axis called SimpleHTTPServer which I'm pretty sure does the same thing but only requires Java 1.5 for those of you stuck with 1.5
I'm not going to explore it since I'm going to use the other solution, so I haven't actually verified it does what I think it does, but I'm pretty sure it does.

Most(/all?) Java SOAP server implementations provide a Servlet (the javax.xml.ws.Endpoint approach in another answer does look a bit simpler though...). Some SOAP implementations you could consider are: Apache CXF: cxf.apache.org, Apache Axis2: ws.apache.org/axis2/ or Spring Web Servies: static.springsource.org/spring-ws/site/ .
The most popular embedded Java web server seems to be Jetty, you can configure it either programatically (using plain Java or Spring beans) or using a custom XML format.

To address the main question directly, another approach would be to go with Jetty's embedded server. See this link for details. The links from the aforelinked page help you understand both the simple web server (i.e., one that serves up static pages; though I am fully aware "simple" is a horribly vague term wrt web servers) and the web server that helps you deploy web services.

Related

How to start a jax-rs server?

I have my endpoints like so:
#Path("/users")
public class Users {
private final SomeDependency dependency
public Users(SomeDependency dependency) {
this.dependency = dependency;
}
#GET
#Path("/{id}")
public Response Get(#PathParam("id") int id) {
User user = this.dependency.get(id);
return Response.ok(user).build();
}
}
Now how do I actually run a server with this endpoint?
I am confused about web servers/applications/servlets, using jersey jetty glassfish or whatever. Also web.xml files? what? ResourceConfigs only accept classes, not their instances. Everything seems to be such a mess.
How can I just do something similar to this?
public static void main(String[] args) throws Exception {
SomeDependency dependency = new SomeDependency();
Users usersEndpoint = new Users(dependency);
Server server = new Server();
server.registerEndpoint(usersEndpoint);
server.start();
}
Server
As far as the server goes, you have two types you have to consider: installed or embedded.
Installed
An installed server is one that is installed on your machine. For example, if you download Tomcat 10 and then follow the installation instruction, the server will get installed on your machine at whatever location you choose. In this situation, when you have an app (a war file) you are ready to deploy, you will copy it to your Tomcat server (to a specific location) and on server startup, Tomcat will see the application and then run it. The applications running in this type of environment will require a web.xml as they are deployed in a war file.
Embedded
An embedded server is one that is packaged into your jar application and is started in a main method just like any other Java SE application. Most installed servers also come with an embedded version. All you need to do is add the server dependencies into your application and then write the server configuration and startup (and shutdown) code. Applications running in this environment will not require a web.xml as they are deployed as a jar file.
Which one to use?
With the advancement and popularity of cloud services and microservices, many applications are moving towards embedded servers. The reason is that they are easy to deploy, are scalable, relatively lightweight, and applications become more self contained. There are many other pros that come with using embedded servers, but there are also some cons. Do your research before you make your final decision about which one you should use.
Example
If you want to quickly get started without having to worry about setting up the project, knowing what dependencies you need to add, adding the startup code, an easy way to get up and running is to use a Maven Archetype. If you go to the Jersey Docs, they get you started with an embedded Grizzly server running a Jersey application. What you need to do is run the following command from the command line (assuming you have Maven installed in your machine)
mvn archetype:generate -DarchetypeArtifactId=jersey-quickstart-grizzly2 \
-DarchetypeGroupId=org.glassfish.jersey.archetypes -DinteractiveMode=false \
-DgroupId=com.example -DartifactId=simple-service -Dpackage=com.example \
-DarchetypeVersion=2.33
If you read the docs I linked to, it will give an explanation of all that comes with the initial application. The main class will look like the following (with comments and imports omitted)
public class Main {
public static final String BASE_URI = "http://localhost:8080/myapp/";
public static HttpServer startServer() {
final ResourceConfig rc = new ResourceConfig().packages("org.example");
return GrizzlyHttpServerFactory.createHttpServer(URI.create(BASE_URI), rc);
}
public static void main(String[] args) throws IOException {
final HttpServer server = startServer();
System.out.println(String.format("Jersey app started with WADL available at "
+ "%sapplication.wadl\nHit enter to stop it...", BASE_URI));
System.in.read();
server.stop();
}
}
In this code, they use the packages() method of the ResourceConfig class that specifies a package for Jersey to scan for #Path and #Provider classes to register. In your case, if you don't need that, you can remove the method call. If you want to register your Users instance, all you do is call register(users) on the ResourceConfig.
See Also
What exactly is the ResourceConfig class in Jersey 2 - this link will help you get started with the ResourceConfig class and show you how you can register you resource classes or instances.
Other Frameworks
There are other frameworks out there that you may also want to consider
Dropwizard - Dropwizard is an opinionated framework built on top of Jersey. It uses an embedded Jetty as its server and comes with many other features to make developing your applications easier. They have pretty good, easy to follow documentation. There is a good "getting started" guide if you want to give them a try.
Spring Boot - Spring Boot is a bootstrapping framework that makes getting up and running with applications much easier. There are auto configurations made for you but give you options to change them. You can use Spring MVC or Jersey as the REST framework when you work with Spring Boot. There is also an Initializer, which is similar to the Maven Archetypes, but is interactive and allows you to add what you want to your applications.
So I just accepted the fact that java is an utter mess and pulled these dependencies in:
<dependency>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-rt-frontend-jaxrs</artifactId>
<version>3.4.2</version>
</dependency>
<dependency>
<groupId>javax.annotation</groupId>
<artifactId>javax.annotation-api</artifactId>
<version>1.2</version>
</dependency>
<dependency>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-rt-transports-http-jetty</artifactId>
<version>3.4.2</version>
</dependency>
So i can launch everything like so:
public static void main(String[] args) throws Exception {
SomeDependency dependency = new SomeDependency();
Users usersEndpoint = new Users(dependency);
JAXRSServerFactoryBean serverFactory = new JAXRSServerFactoryBean();
serverFactory.setResourceClasses(usersEndpoint.getClass());
serverFactory.setResourceProvider(usersEndpoint.getClass(), new SingletonResourceProvider(usersEndpoint));
serverFactory.setAddress("http://localhost:8080/");
serverFactory.create().start();
}
I have more endpoints, of course, so I put everything in a for loop.
As to why I'm answering from a guest account, the account I used to ask this question was created using a disposable email address, and I can no longer access it.
Hope this helps anyone in the future!

Invoke a GWT RPC Service from Java, problems with RPC policy

I need to invoke a GWT RPC service from simple Java code. Yes, I read this
Invoke a GWT RPC service from Java directly
However, my issue is that I do not have access to the web application code (though I could ask and obtain some parts of it), so I cannot just add it to the build path of my Java project. All the info I read from the internet is not clear on what exactly needs to be imported.
The question is: what is the minumum that I should include in my project in order to make the call to the service work (using syncproxy gwt for example)? Will it be enough to redefine the client interfaces inside my code or should I do some compiling work as well?
EDIT: I've done some testing locally with the default web app running on localhost. I created a new java project, imported the sync and async service interfaces and the RPC serialization policy I found in the WAR folder of the web app. This is my testing code
import com.gdevelop.gwt.syncrpc.SyncProxy;
public class serviceCall {
private static final String MODULE_BASE_URL = "http://127.0.0.1:8888/gwttestapp/";
private static final String SERVICE_NAME = "greet";
public static void main(String[] args) {
GreetingService rpcService = (GreetingService) SyncProxy.newProxyInstance(GreetingService.class, MODULE_BASE_URL, SERVICE_NAME, "CB32CC2E454EE7E1088B2E29CEB44F84");
String result = rpcService.greetServer("SyncProxy");
}
}
However the server seems not to recognize the RPC policy, since I get the following exception:
Exception in thread "main" com.google.gwt.user.client.rpc.IncompatibleRemoteServiceException: This application is out of date, please click the refresh button on your browser. ( Blocked attempt to access interface 'GreetingService', which is not implemented by 'com.apptesting.server.GreetingServiceImpl'; this is either misconfiguration or a hack attempt )
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:57)
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
at java.lang.reflect.Constructor.newInstance(Constructor.java:525)
at com.gdevelop.gwt.syncrpc.SyncClientSerializationStreamReader.instantiate(SyncClientSerializationStreamReader.java:746)
at com.gdevelop.gwt.syncrpc.SyncClientSerializationStreamReader.deserialize(SyncClientSerializationStreamReader.java:816)
at com.google.gwt.user.client.rpc.impl.AbstractSerializationStreamReader.readObject(AbstractSerializationStreamReader.java:119)
at com.gdevelop.gwt.syncrpc.RemoteServiceSyncProxy.doInvoke(RemoteServiceSyncProxy.java:204)
at com.gdevelop.gwt.syncrpc.RemoteServiceInvocationHandler.invoke(RemoteServiceInvocationHandler.java:193)
at com.sun.proxy.$Proxy0.greetServer(Unknown Source)
at serviceCall.main(serviceCall.java:11)
Anybody can help?
Try initiating the rpcService without the .gwt.rpc policy specified. IE, just make the call:
GreetingService rpcService = (GreetingService) SyncProxy.newProxyInstance(GreetingService.class, MODULE_BASE_URL, SERVICE_NAME);
You generally do not need to specify the exact serialization policy as the RPC system should automatically figure it out. In fact, it's better not to specify it because the deployed site will change the serialization policy file as the back-end changes. Take a look at the source and testing wiki (https://code.google.com/p/gwt-syncproxy/wiki/SourceAndTesting) for some guidance on on setup need needs. The source code for the Android testing app may provide you some code guidance on creating a functional standalone (if you ignore the AsyncCallback implementations)
In general answer to your question, for deployment purposes, all you really are the interfaces you specified (*Service & *ServiceAsync). For testing purposes in your development environment, you can mock some *Impl files that will provide you some generic responses for testing (such as in the default web-app). Take a look at the Android Wiki in the sync-proxy project (https://code.google.com/p/gwt-syncproxy/wiki/Android) at the setup section for a quick overview on linking the needed files.
Disclaimer: I'm a developer for the Android syncproxy library

How can I run a Java app on Apache 2.2 without Tomcat?

I'm building a webservice with Java that does not use JSP or servlets, and want to run it on my Apache HTTP server without having to install and configure Tomcat. Is this possible (easily), and how can I go about it?
I've been searching for information on this and the only thing I've come across is the mod_jk Tomcat connector which still requires Tomcat to be installed. Am I missing something?
Of course It is possible. You could do It using mod_cgi.
A very simple example would be like this:
public class HelloWorld
{
public static void main(String[] args)
{
System.out.println("Hello Java CGI world!");
}
}
and then a script file (HelloWorld.shtml -do not forget the execute permission) that executes the Java class
#!/bin/bash
echo "Content-type: text/html"
echo ""
/usr/bin/java HelloWorld
In Apache conf, just define your script directory, something like this:
ScriptAlias /cgi-bin/ /Users/hectorsuarez/Proyectos/test/cgi-bin/
<Directory "/Users/hectorsuarez/Proyectos/test/cgi-bin">
SetHandler cgi-script
Options ExecCGI
Order allow,deny
Allow from all
</Directory>
That's it!. This is a very simple and trivial example.
This will get complicated because you could probably need a template engine and a much better way to manage the incoming CGI calls. But yes, It is possible.
First of all, Servlets is the very basics of Java for Web development. So, whatever web development you are doing, like Web Services, you'll need a Servlet Container, as Tomcat.
So the answer to your question is "you cant run it's only on Apache HTTP Server", because it's not a Servlet Container.
It is not entirely clear what you want to do, but I'm going to guess that you want to run a stand-alone Java app which can handle HTTP requests and expose it via Apache. If that's the case, you can do it by configuring Apache with mod_proxy. This might be a decent example of how this could be done.
No, Tomcat, jetty, jboss or Glassfish is pretty much mandatory

JMX Html Adaptor

I'm looking for a simple and straightforward way to add JMX capacities to application, preferably exposed via http. Below is simple code snippet, which, I suspect, should run http server on 8000. And I should be able to access it via http://localhost:8000. However page can't be opened. I can't find proper documentation how it is supposed to work.
jmxtools-1.2.jar is included to classpath. Java version - 1.6
import javax.management.MBeanServerFactory;
import javax.management.ObjectName;
import com.sun.jdmk.comm.HtmlAdaptorServer;
public class JmxHttpAdapter {
public static void main(String[] args) {
try {
com.sun.jdmk.comm.HtmlAdaptorServer adapter = new HtmlAdaptorServer(8000);
MBeanServerFactory.createMBeanServer().registerMBean(adapter, new ObjectName("Adaptor:name=html,port=8000"));
adapter.start();
Thread.sleep(100000);
} catch (Exception ex) {
ex.printStackTrace();
}
}
}
Not sure why that adaptor is not working, but you can find documentation in Chapter 2 of the Java Dynamic Management Kit 5.1 Tools Reference Guide.
MX4J also has an HTTP Adaptor which is also kind of old, but you may find it better documented.
You should take a look at Jolokia. It is more contemporary and still under active development. It is an HTTP based REST agent with several options for installation including a WAR and a Java Agent. That does not get you a UI though, although there's plenty of tools you can use with it. The same developer is working on a UI project for Jolokia called Aji but I am not sure what state is in right now.
Here's a few references to UIs built for Aji:
Jolokia + Highcharts = JMX for human beings
JMX over HTTP with Jolokia and javascript

Add a web service to a already available Java project

I'm new to Java. I have a Java project. It runs perfectly on my Windows 7 machine. I want to use some of the functionalities of this project as Web Services to be able to use them in my Silverlight app. Both the Silverlight app and this Java project would be on the single server machine. The problem I have is that when I right click on the project there's no Web Service in the New menu. What should I do to add a web service to my project? Thanks.
Based on the article I linked in the comments above :: http://www.ibm.com/developerworks/webservices/tutorials/ws-eclipse-javase1/index.html
With the JWS annotations you can setup a Web Service in your java application to expose some of its functionality. There is no extra libraries needed. The below examples were written with Java 6.
An example of Defining your web service :
import javax.jws.WebMethod;
import javax.jws.WebService;
#WebService
public class MyWebService {
#WebMethod
public String myMethod(){
return "Hello World";
}
}
Note the 2 annotations of #WebService and #WebMethod. Read their API's which are linked and configure them as required. This example will work without changing a thing
You then only need to setup the Listener. You will find that in the class javax.xml.ws.Endpoint
import javax.xml.ws.Endpoint;
public class Driver {
public static void main(String[] args) {
String address = "http://127.0.0.1:8023/_WebServiceDemo";
Endpoint.publish(address, new MyWebService());
System.out.println("Listening: " + address);
}
}
Run this program and you will be able to hit your web service using http://127.0.0.1:8023/_WebServiceDemo?WSDL. At this point it is easy to configure what you want to send back and forth between the applications.
As you can see there is no need to setup a special web service project for your use.

Categories

Resources