soap sucks doesn’t it? - eclipsecon europe 2019 · soap sucks doesn’t it? tom bujok geecon...
TRANSCRIPT
SOAP SUCKS DOESN’T IT?
ABOUT METom(EK|ASZ){0,1} BUJOkcenteractive ag, BERN, [email protected]
http://assets3.notonthehighstreet.com/system/product_images/images/000/502/304/normal_SIWS_-_Good_Clean_Fun.jpg?1335135213
SOAP...
XML PARSING<?xml version="1.0" encoding="UTF-8"?><stocks> <stock> <symbol>Citibank</symbol> <price>100</price> <quantity>1000</quantity> </stock> <stock> <symbol>UBS</symbol> <price>90</price> <quantity>2000</quantity> </stock></stocks>
JAVADocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();DocumentBuilder dBuilder = dbFactory.newDocumentBuilder();Document doc = dBuilder.parse(stocks);doc.getDocumentElement().normalize();NodeList nodes = doc.getElementsByTagName("stock");for (int i = 0; i < nodes.getLength(); i++) { Node node = nodes.item(i); if (node.getNodeType() == Node.ELEMENT_NODE) { Element el = (Element) node; NodeList list = el.getElementsByTagName("symbol") NodeList children = list.item(0).getChildNodes(); String value = children(0).getNodeValue(); } }}
JAVADocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();DocumentBuilder dBuilder = dbFactory.newDocumentBuilder();Document doc = dBuilder.parse(stocks);doc.getDocumentElement().normalize();NodeList nodes = doc.getElementsByTagName("stock");for (int i = 0; i < nodes.getLength(); i++) { Node node = nodes.item(i); if (node.getNodeType() == Node.ELEMENT_NODE) { Element el = (Element) node; NodeList list = el.getElementsByTagName("symbol") NodeList children = list.item(0).getChildNodes(); String value = children(0).getNodeValue(); } }}
JAVADocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();DocumentBuilder dBuilder = dbFactory.newDocumentBuilder();Document doc = dBuilder.parse(stocks);doc.getDocumentElement().normalize();NodeList nodes = doc.getElementsByTagName("stock");for (int i = 0; i < nodes.getLength(); i++) { Node node = nodes.item(i); if (node.getNodeType() == Node.ELEMENT_NODE) { Element el = (Element) node; NodeList list = el.getElementsByTagName("symbol") NodeList children = list.item(0).getChildNodes(); String value = children(0).getNodeValue(); } }}
JAVADocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();DocumentBuilder dBuilder = dbFactory.newDocumentBuilder();Document doc = dBuilder.parse(stocks);doc.getDocumentElement().normalize();NodeList nodes = doc.getElementsByTagName("stock");for (int i = 0; i < nodes.getLength(); i++) { Node node = nodes.item(i); if (node.getNodeType() == Node.ELEMENT_NODE) { Element el = (Element) node; NodeList list = el.getElementsByTagName("symbol") NodeList children = list.item(0).getChildNodes(); String value = children(0).getNodeValue(); } }}
I am curious what is the purpose of normalize(). I have tried to surf but couldn't find any useful stuff.
forums.oracle.com
In cases where the document contains CDATASections, the normalize operation alone may not be sufficient, since XPointers do not differentiate between Text nodes and CDATASection nodes.
JAVADocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();DocumentBuilder dBuilder = dbFactory.newDocumentBuilder();Document doc = dBuilder.parse(stocks);doc.getDocumentElement().normalize();NodeList nodes = doc.getElementsByTagName("stock");for (int i = 0; i < nodes.getLength(); i++) { Node node = nodes.item(i); if (node.getNodeType() == Node.ELEMENT_NODE) { Element el = (Element) node; NodeList list = el.getElementsByTagName("symbol") NodeList children = list.item(0).getChildNodes(); String value = children(0).getNodeValue(); } }}
JAVADocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();DocumentBuilder dBuilder = dbFactory.newDocumentBuilder();Document doc = dBuilder.parse(stocks);doc.getDocumentElement().normalize();NodeList nodes = doc.getElementsByTagName("stock");for (int i = 0; i < nodes.getLength(); i++) { Node node = nodes.item(i); if (node.getNodeType() == Node.ELEMENT_NODE) { Element el = (Element) node; NodeList list = el.getElementsByTagName("symbol") NodeList children = list.item(0).getChildNodes(); String value = children(0).getNodeValue(); } }}
JAVADocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();DocumentBuilder dBuilder = dbFactory.newDocumentBuilder();Document doc = dBuilder.parse(stocks);doc.getDocumentElement().normalize();NodeList nodes = doc.getElementsByTagName("stock");for (int i = 0; i < nodes.getLength(); i++) { Node node = nodes.item(i); if (node.getNodeType() == Node.ELEMENT_NODE) { Element el = (Element) node; NodeList list = el.getElementsByTagName("symbol") NodeList children = list.item(0).getChildNodes(); String value = children(0).getNodeValue(); } }}
JAVADocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();DocumentBuilder dBuilder = dbFactory.newDocumentBuilder();Document doc = dBuilder.parse(stocks);doc.getDocumentElement().normalize();NodeList nodes = doc.getElementsByTagName("stock");for (int i = 0; i < nodes.getLength(); i++) { Node node = nodes.item(i); if (node.getNodeType() == Node.ELEMENT_NODE) { Element el = (Element) node; NodeList list = el.getElementsByTagName("symbol") NodeList children = list.item(0).getChildNodes(); System.out.println(children(0).getNodeValue()); } }}
7 MINUT
WEB-SERVICE STACKS
‣ APACHE AXIS 1.4 (✝2006)‣ XFIRE 1.2.6 (✝2007)‣ APACHE AXIS 2 1.6.2‣ Apache cxf 2.7.0
‣ SPRING-WS 2.1.1 ‣ JAX-WS RI 2.2.7 ‣ GLASSFISh METRO 2.2.1-1 ‣ WSo2
@WebService(name = "PersonService")public class PersonService { public Person getPerson(String uuid) { return new Person(); }}
@XmlAccessorType(XmlAccessType.FIELD)@XmlRootElement(namespace = "http://jdays/person")public class Person { String uuid; String firstName; String lastName;}
tIGHT-COUPLING vs. DTO (ANTI) PATTERN
@WebMethod(action = "urn:getBook") @WebResult(name = "getBookReturn", targetNamespace = "http://jdays/library/wsdl") @RequestWrapper(localName = "getBook", targetNamespace = "http://jdays/library/wsdl", className = "se.jdays.GetBook") @ResponseWrapper(localName = "getBookResponse", targetNamespace = "http://jdays/library/wsdl", className = "se.jdays.GetBookResponse") public Book getName( @WebParam(name = "isbn", targetNamespace = "http://jdays/library/wsdl") String isbn);
CODE-FIRST (ANTI) pattern
├── resources│ ├── CustomerService.wsdl│ ├── binding.xml│ ├── client-applicationContext.xml│ ├── cxf.xml│ └── server-applicationContext.xml└── webapp └── WEB-INF ├── cxf-servlet.xml └── web.xml
IS IT REALLY THAT EASY (CLIENT <-> SERVER)?‣ ant / maven‣ CXF-CODEGEN PLUGIN‣ BUILDEr-HELPER-PLUGIN ‣ WAR-PLUGIN‣ JETTY-PLUGIN
is THIS SOAP REALLY clean?
http://assets3.notonthehighstreet.com/system/product_images/images/000/502/304/normal_SIWS_-_Good_Clean_Fun.jpg?1335135213
def url="api.twitter.com/1/statuses/user_timeline.json"def response = ("https://$url?id=tombujok").toURL().textprintln new JsonSlurper().parseText(response)?.text.first()
GROOVY REST CLIENT 15 minut
WSDL STRUCTURE
T Y P E
M E S S A G E
P O R T T Y P E
B I N D I N G
S E R V I C E
P O R T S
O P E R A T I O N
SOAP BINDING STYLES
‣ RPC-ENCODED‣ RPC-LITERAL‣ DOCUMENT-ENCODED‣ DOCUMENT-LITERAL‣ DOCUMENT-LITERAL-WRAPPED
http://www.ibm.com/developerworks/webservices/library/ws-whichwsdl/
SOAP MESSAGE RPC-ENCODED<soap:envelope> <soap:body> <myMethod> <x xsi:type="xsd:int">5</x> <y xsi:type="xsd:float">5.0</y> </myMethod> </soap:body></soap:envelope>
SOAP MESSAGE RPC-LITERAL<soap:envelope> <soap:body> <myMethod> <x>5</x> <y>5.0</y> </myMethod> </soap:body></soap:envelope>
SOAP MESSAGE DOCUMENT-LITERAL<soap:envelope> <soap:body> <xElement>5</xElement> <yElement>5.0</yElement> </soap:body></soap:envelope>
SOAP BUILDER - ONE LINER
String message = Wsdl .parse(WSDL_URL) .binding().localPart(BINDING_NAME).find() .operation().soapAction(SOAP_ACTION).find() .buildInputMessage()
SOAP BUILDERString url = "http://CurrencyConvertor.com?WSDL";WsdlParser parser = WsdlParser.parse(url);
SoapBuilder builder = parser.binding() .localPart("CurrencyConvertorSoap") .builder();
SoapOperation operation = builder.operation() .soapAction("http://ConversionRate") .find();
String input = builder.buildInputMessage(operation);
SOAP BUILDER - INTERFACEString buildInputMessage()
String buildOutputMessage()
String buildFault(String code, String message)
String buildEmptyFault()
String buildEmptyMessage()
SOAP CONTEXTSoapContext context = SoapContext.builder() .alwaysBuildHeaders(true) .buildOptional(true) .exampleContent(true) .typeComments(false) .valueComments(false) .excludedTypes(types) .multiValuesProvider(provider) .build()
SOAP CLIENTSoapClient client = SoapClient.builder() .endpointUrl("http://service.com/endpoint") .basicAuth("user", "pass") .connectTimeoutInMillis(30000) .readTimeoutInMillis(10000) .build();
client.post(soapAction, message)
P R O X Y S S L T R U S T S T O R E
SOAP SERVERSoapServer server = SoapServer.builder() .httpPort(8080) .acceptorThreads(4) .maxThreads(8) .reuseAddress(true) .build()
server.start()server.stop()
T I M E O U T S H T T P S K E Y S T O R E
SOAP ENDPOINTSAutoResponder responder = new AutoResponder(builder);
server.registerRequestResponder("/service", responder);
server.unregisterRequestResponder("/service");
Request RESPONDER
public interface RequestResponder {
/** * Returns a response to a SOAP message. * <p/> * @param request SOAP message to handle * @return XML response with the whole SOAP envelope */ javax.xml.Source respond(SoapMessage request);
}
ABSTRACT RESPONDERpublic abstract class AbstractResponder implements RequestResponder { // ... /** * @param invokedOperation op matched to the SOAP msg * @param message SOAP message passed by the client * @return XML response with the whole SOAP envelope */ public abstract javax.xml.Source respond( SoapOperation invokedOperation, SoapMessage message );}
Custom RESPONDERnew AbstractResponder(builder) { @Override public Source respond(SoapOperation operation, SoapMessage message) { // build the response using builder String response = builder.buildOutputMessage(operation) // here you can tweak the response //... return XmlUtils.xmlStringToSource(response) }};
WHY WOULD WE DO THAT???
We currently run our web services with Tomcat and SpringFramework, using Axis2 to generate Java modules from our WSDLs. Our goal was to look for an alternative to avoid constant code changes whenever the WSDL was modified.
Tracy:
WHY WOULD WE DO THAT???
We create a proxy layer so that company A does not talk to company B directly. The entire layer does not care about the WSDL structure, it sits between two companies for doing logging, queing, load-balancing, authentication, authorization, translation, etc.
Hemant:
WHY WOULD WE DO THAT???
...another issue was that the webservice was going to be changing a fair bit over the first year as other functionality was added and the service offerings changed. Having to go through the 'wsdl2java' approach every change would have been a lot of work.
Ken:
SOAP with CODE - 1 version
W S D L
S T U B SB U S I N E S S
L O G I C S T U B SB U S I N E S S
L O G I C
SERVER CLIENt
SOAP
SOAP with CODE - 2 versions
W S D L
S T U B S
B U S I N E S SL O G I C
SERVER
SOAP
W S D L ’
S T U B S ’
S T U B S
B U S I N E S SL O G I C
CLIENt
S T U B S ’SOAP
COMPONENT COMPATIBLE INCOMPATIBLE
SOAP HEADER ADD OPTIONAL CHANGE, REMOVE OPT.ADD, CHANGE, REMOVE REQ.
PARAMETER ADD OPTIONAL IN REQUEST ADD, CHANGE, REMOVE
OPERATION ADD A NEW OPERATION CHANGE, REMOVE
RESPONSE CHANGE
WS BACKWARD COMPATIBILITY
http://help.yahoo.com/l/us/yahoo/ewsapt/webservices/support/wss_faq_versioning.html
WISDOM BY BIG-BROTHERS‣ LAYER OF INDIRECTION PATTERN‣ ORACLE SERVICE BUS‣ ORACLE PORTAL SERVER
http://www.newhorizons.com/LOCALWEBADMIN/images/306/outlines/partner%20images/logo-oracle-large.jpghttp://www.oracle.com/technetwork/articles/web-services-versioning-094384.html
WISDOM BY BIG-BROTHERS‣ IBM WEB-SPHERE UDDI‣ IBM WEB-SPHERE SERVER
http://upload.wikimedia.org/wikipedia/commons/5/51/IBM_logo.svghttp://www.ibm.com/developerworks/webservices/library/ws-uddisecure/
SOAP with CODE - WISDOM FROM THE WEB
W S D L
S T U B S
B U S I N E S SL O G I C
SERVER
W S D L ’
S T U B S ’
http://www.gridshore.nl/blog/index.php?/archives/68-Web-service-versioning-in-the-java-world.htmlfindicons.com/icon/130548/llama_glyph?id=130575
LoL
SOAP with CODE - WISDOM FROM THE WEB
W S D L
S T U B S
B U S I N E S SL O G I C
SERVER
W S D L ’
S T U B S ’
http://www.gridshore.nl/blog/index.php?/archives/68-Web-service-versioning-in-the-java-world.html
NO VERSIONINGForce clients to migrate
LoLfindicons.com/icon/130548/llama_glyph?id=130575
SOAP with CODE - WISDOM FROM THE WEB
W S D L
S T U B S
B U S I N E S SL O G I C
SERVER
W S D L ’
S T U B S ’
http://www.gridshore.nl/blog/index.php?/archives/68-Web-service-versioning-in-the-java-world.html
DIFFERENT PACKAGEs
LoLfindicons.com/icon/130548/llama_glyph?id=130575
SOAP with CODE - WISDOM FROM THE WEB
W S D L
S T U B SB U S I N E S S
L O G I C
http://www.gridshore.nl/blog/index.php?/archives/68-Web-service-versioning-in-the-java-world.html
DIFFERENT ARTIFACTS
LoLfindicons.com/icon/130548/llama_glyph?id=130575
B U S I N E S SL O G I C
SERVER
W S D L ’
S T U B S ’
SOAP with CODE - WISDOM FROM THE WEB
W S D L
S T U B SB U S I N E S S
L O G I C
http://www.gridshore.nl/blog/index.php?/archives/68-Web-service-versioning-in-the-java-world.html
MEDIATION BY HANDLoL
findicons.com/icon/130548/llama_glyph?id=130575
SERVER
W S D L ’
S T U B S ’
W S D L
S T U B S
MEDIATOR
SOAP-WS - VERSIONING MADE EASY
B U S I N E S SL O G I C
SERVER
B U I L D E R S U P P L E M E N T S E R V E R
SOAP-WS - VERSIONING MADE EASY
SERVER
D B F I L E
B U S I N E S SL O G I C
B U I L D E R S U P P L E M E N T S E R V E R
S E R V E R ’B U I L D E R ’ S U P P L E M E N T ’
SOAP TESTING DONE RIGHT@Server(wsdl = "http://srv.com?wsdl", binding = "Binding")public class TestExample {
@Test @Server(wsdl = URL, binding = "Binding", port = 41414) public void testSoapMock_serverPerMethod() { }
@Test public void testSoapMock_serverPerClass() { }
}
FULL SPRING INTEGRATION<bean id="soapServerFactory" class="com.centeractive.ws.server.core.SoapServerFactory"> <property name="httpPort" value="8778"/> <property name="responders"> <map> <entry key="/currencyConverter/soap" value-ref="autoResponder" /> </map> </property></bean>
FULL SPRING INTEGRATION@Autowiredprivate SoapBuilder builder;
@Autowiredprivate SoapClient client;
@Autowiredprivate SoapServer server;
SOAP-ws ROADMAP
GROOVY MODULE
GRAILS PLUGIN
GRIFFON PLUGINARQUILLAN
deista.files.wordpress.com/2011/04/internet-explorer-y-mozilla-firefox.jpg?w=640
WEB-CONTAINERs
HTTP BINDING
WS-SECURITY
cdn1.iconfinder.com/data/icons/secureicons/png/512/PadLock.png
WS-ATTACHMENT
cdn1.iconfinder.com/data/icons/softwaredemo/PNG/256x256/PaperClip4_Black.png
WS-ADDRESSING
cdn1.iconfinder.com/data/icons/Primo_Icons/PNG/128x128/address_black.png
SPRING-WS
THANK YOU
TOM BUJOK
GeeCON CONFERENCE 16th of MAY 2013
@TOMBUJOKWWW.REFICIO.ORG
http://gamedevwithoutacause.com/wp-content/uploads/2011/11/singleton-12yr.jpeg