4. JavaWebServices
• known bugs (e. g. problems with https)
• bugs with mapping of complex data types (uses Axis 1.x)
• clumsy (Axis 1.x)
• complicated (Axis 1.x)
• slow (Axis 1.x)
• consider it broken
5. Alternatives?
• AXIS 2
‣ POJO for services and
mapped data
‣ service definitions in
separate files
‣ rewritten from scratch
!
• Jax WS
‣ POJO for services and
mapped data
‣ all definitions using Java
Annotations
‣ part of Standard Java!
6. ERJaxWS
• Jax WS RI Libraries
• ERJaxWebServiceRequestHandler
adapting WORequest to Jax WS internal engine for handling servlet requests
• NOT API compatible to JavaWebServices
• provide new SOAP service
• provide SOAP service based on imported WSDL
• call external SOAP service based on imported WSDL
7. Provide own SOAP service - 1
package your.app.ws;
!
import javax.jws.WebService;
!
@WebService
!
public class Calculator {
!
public int add(int a, int b)
{
return a + b;
}
}
8. Provide own SOAP service - 2
package your.app;
!
import javax.xml.ws.Endpoint;
!
import er.extensions.appserver.ERXApplication;
import er.extensions.appserver.ws.ERJaxWebService;
import er.extensions.appserver.ws.ERJaxWebServiceRequestHandler;
!
public class Application extends ERXApplication {
!
public static void main(String[] argv) {
ERXApplication.main(argv, Application.class);
}
!
public Application() {
setAllowsConcurrentRequestHandling(true);
// do it the WONDER way
ERJaxWebServiceRequestHandler wsHandler = new ERJaxWebServiceRequestHandler();
wsHandler.registerWebService("Calculator", new ERJaxWebService<Calculator>(Calculator.class));
this.registerRequestHandler(wsHandler, this.webServiceRequestHandlerKey());
!
// create a standalone endpoint using Jax WS mechanisms
Endpoint.publish("http://localhost:9999/ws/Calculator", new Calculator());
!
}
}
10. Provide SOAP service based on WSDL
// Import WSDL and create interface and classes for mapped data
$ wsimport -keep -s Sources http://localhost:port/cgi-bin/WebObjects/WebService1.woa/ws/Calculator?wsdl
!
// Import WSDL and create jar
$ wsimport -clientjar Libraries/myservice.jar http://localhost:port/cgi-bin/WebObjects/WebService1.woa/ws/Calculator?wsdl
!
!
!
// create CalculatorImplementation
package your.app;
!
import javax.jws.WebService;
!
@WebService(endpointInterface = "your.app.Calculator")
!
public class CalculatorImpl implements Calculator
{
!
@Override
public int add(int arg0, int arg1) {
return arg0 + arg1;
}
!
}
12. Java Annotations / WebService
• @WebService
name, namespace, service interface
• @BindingType
SOAP version
• @SOAPBinding
WSDL document styles
• @WebMethod
name, exclusion
• @WebParam
name
• @WebResult
name
13. Call a remote SOAP service
URL url = new URL("http://127.0.0.1:3333/cgi-bin/WebObjects/JaxServerTest.woa/ws/Hello?wsdl");
!
// 1st argument service URI, refer to wsdl document above
// 2nd argument is service name, refer to wsdl document above
QName qname = new QName("http://app.your/", "HelloImplService");
!
Service service = Service.create(url, qname);
!
Hello remoteHello = service.getPort(Hello.class);
!
remoteHello.hello("Jon Doe“);
!
!
!
// BETTER: use imported interface
!
HelloImplService service = new HelloImplService(url);
!
Hello remoteHello = service.getPort(Hello.class);
!
remoteHello.hello("Jon Doe“);
!
14. Data mapping
• JAXB
• all native Java data types
• all "Bean" classes
• custom type adaptors
15. custom data mapping - 1
!
!
!
public class WSStruct
{
!
public String name;
!
public int zip;
!
public MyCustomDate myDate;
!
public NSTimestamp datetime;
}
16. custom data mapping - 2
@XmlType(name = "WSStructType", propOrder = {"name", "zip", "datetime"})
@XmlAccessorType(value = XmlAccessType.PUBLIC_MEMBER)
!
public class WSStruct
{
@XmlElement
public String name;
@XmlAttribute
public int zip;
@XmlTransient
public MyCustomDate myDate;
!
public NSTimestamp datetime;
}
17. custom data mapping - 3
@XmlType(name = "WSStructType", propOrder = {"name", "zip", "datetime"})
@XmlAccessorType(value = XmlAccessType.PUBLIC_MEMBER)
!
public class WSStruct
{
@XmlElement
public String name;
@XmlAttribute
public int zip;
@XmlTransient
public MyCustomDate myDate;
@XmlJavaTypeAdapter(value = NSTimestampAdapter.class)
public NSTimestamp datetime;
}
class NSTimestampAdapter extends XmlAdapter<String, NSTimestamp>
{
private final NSTimestampFormatter formatter = new NSTimestampFormatter();
public NSTimestamp unmarshal(String v) throws Exception {
return (NSTimestamp) formatter.parseObject(v);
}
public String marshal(NSTimestamp v) throws Exception {
return formatter.format(v);
}
}
18. Data mapping
• Directly map EOs? NO!
• might change
• would need to adapt your EO templates
• avoid marshalling your complete data tree
19. WebFaults
• WebServices exceptions can be defined as WebFaults
• Beware: serialized info is not in Exception but in a referred
WebFault bean
• stack traces possible
switch off with property
com.sun.xml.ws.fault.SOAPFaultBuilder.disableCaptureStackTrace=false
20. WebFault sample
@WebFault(faultBean = "TestServiceFaultInfo")
public class TestServiceException extends Exception
{
private TestServiceFaultInfo code;
public TestServiceException(String message, TestServiceFaultInfo info) {
super(message);
this.code = info;
}
public TestServiceFaultInfo getFaultInfo() {
return code;
}
}
!
public class TestServiceFaultInfo
{
public String msg;
!
public TestServiceFaultInfo() {
}
!
public TestServiceFaultInfo(String msg) {
this.msg = msg;
}
}
21. Stateful Services
• @Stateful - makes no sense in WebObjects env
• Jax WS injects a RequestContext into your Service object
• gives access to WOContext and by that to your Session
• creates WebObjects Cookies as usual
• enable session persistence in your client proxy
23. Secure WebServices
• basic auth by common means
• create your own custom ERJaxWebService
• @SOAPMessageHandler
declare your own Jax WS message handlers
for example for handling signed SOAP messages