In the previous post we created a simple Web Service in Java. Now we’ll build on it, by providing more methods with standard argument and return types.
- String
- Number
- Boolean
- Array
- Variable arguments
Let’s recall the Web Service with a single available operation.
@WebService
@SOAPBinding(style=Style.RPC)
public interface SimpleService {
@WebMethod
String sayHello();
}
Strings
Apart from sayHello, we would like a new operation that says hello to a given name.
@WebService
@SOAPBinding(style=Style.RPC)
public interface SimpleService {
@WebMethod
String sayHello();
@WebMethod
String sayHelloTo(String name);
}
Let’s implement it.
@WebService(endpointInterface="simple.SimpleService")
public class SimpleServiceImpl implements SimpleService {
public String sayHello() {
return "Hello from Web Services!";
}
public String sayHelloTo(String name) {
return String.format("Hello %s!", name);
}
}
If we publish the Web Service and access its WSDL, we’ll notice some new lines.
... <message name="sayHelloTo"> <part name="arg0" type="xsd:string"/> </message> ...
Booleans and Numbers
Here is another operation that determines whether an integer is even.
public interface SimpleService {
...
@WebMethod
boolean isEven(int input);
...
}
Its implementation is straight-forward.
public class SimpleServiceImpl implements SimpleService {
...
public boolean isEven(int input) {
return input % 2 == 0;
}
...
}
When the service is published, notice that the following lines are added to the WSDL.
... <message name="isEven"> <part name="arg0" type="xsd:int"/> </message> <message name="isEvenResponse"> <part name="return" type="xsd:boolean"/> </message> ...
Arrays and var-args
The last operation of our Web Service is to reverse an array.
public interface SimpleService {
...
@WebMethod
String[] reverse(String... input);
...
}
The equivalent entries in the WSDL contract are the following.
... <message name="reverse"> <part name="arg0" type="ns1:stringArray"/> </message> <message name="reverseResponse"> <part name="return" type="ns2:stringArray"/> </message> ...
The complete code follows.
The Web Service:
@WebService @SOAPBinding(style=Style.RPC) public interface SimpleService { @WebMethod String sayHello(); @WebMethod String sayHelloTo(String name); @WebMethod boolean isEven(int input); @WebMethod String[] reverse(String... input); }
API: WebService, WebMethod, SOAPBinding, SOAPBinding.Style
@WebService(endpointInterface="simple.SimpleService")
public class SimpleServiceImpl implements SimpleService {
public String sayHello() {
return "Hello from Web Services!";
}
public String sayHelloTo(String name) {
return String.format("Hello %s!", name);
}
public boolean isEven(int input) {
return input % 2 == 0;
}
public String[] reverse(String... input) {
if (input == null) return null;
final String[] result = new String[input.length];
for (int index = 0; index < input.length; index++) {
result[index] = input[input.length - 1 - index];
}
return result;
}
}
The publisher:
public class SimpleServicePublisher {
/**
* Publishes the Web Service locally.
*/
public static void main(String[] args) {
Endpoint.publish("http://127.0.0.1:9000/simple", new SimpleServiceImpl());
}
}
API: Endpoint
The client:
public class SimpleServiceClient {
public static void main(String[] args) throws Exception {
// Connect to the Web Service
final URL url = new URL("http://127.0.0.1:9000/simple");
final QName name = new QName("http://simple/", "SimpleServiceImplService");
final Service service = Service.create(url, name);
final SimpleService simple = service.getPort(SimpleService.class);
// Call some operations
System.out.println(simple.sayHello());
System.out.println(simple.sayHelloTo("Nikos"));
int number = 32;
System.out.format("The number %d is %seven.\n", number, simple.isEven(number) ? "" : "not ");
String[] result = simple.reverse("Nikos", "Sofia", "Eleni");
for (String element : result) {
System.out.println(element);
}
}
}
Summary
The Web Services remain really simple, when the methods use standard Java types.
| Java type | Schema type |
|---|---|
| String | string |
| Integer | int |
| Boolean | boolean |
| String[] | stringArray |
| String… | stringArray |
In the next post, we’ll use more complex types; this will require just a single extra configuration step.
Thanks.
this is a very very good article
Again, this is very informative and easy to implement. However, I’m not sure if you ever got around to doing that “next post”, in which you use more complex types.
That post would be REALLY informative and useful.
Any chance of that happening?
Thanks again. This stuff is great.
Hi.
I’ve noticed that when the client executes
service.getPort(SimpleService.class);
the server will log the following exception, but still return the proper response to the client when running locally:
Jul 26, 2011 11:20:56 AM com.sun.xml.internal.ws.transport.http.HttpAdapter$HttpToolkit handle
SEVERE: Request doesnt have a Content-Type
com.sun.xml.internal.ws.server.UnsupportedMediaException: Request doesnt have a Content-Type
Is there some other specification that one needs to satisfy the server? I’ve also noticed that the first argument of the QName constructor seems to have to be the package backwards. For example, my package is com.billybyte.simplewebservice. The first argument in the QName constructor that works is “http://simplewebservice.billybyte.com”
Does this make sense?
Thanks much for your posts.
Reblogged this on Zeeshan Akhter.
Is there a way I can return a custom class?