Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Flexible EAI-Lösungen mit GlassFish

Flexible EAI-Lösungen mit GlassFish

Vortrag beim DOAG SIG Middleware GlassFish Event mit Martin Huber (@waterback). http://www.doag.org/termine/termine.php?tid=450909

Alexander Heusingfeld

October 08, 2013
Tweet

More Decks by Alexander Heusingfeld

Other Decks in Programming

Transcript

  1. We take care of it - personally! © 2013 innoQ

    Deutschland GmbH Flexible EAI-Lösungen mit Glassfish Praxisbeispiele und War Stories zu EAI-Pattern Alexander Heusingfeld, @goldstift Martin Huber, @waterback Tuesday 8 October 13
  2. © 2013 innoQ Deutschland GmbH EAI Pattern in 2013? Nobody

    does that anymore! Tuesday 8 October 13
  3. © 2013 innoQ Deutschland GmbH Multitude of potential service consumers

    Integration is ubiquitous CRM Application Tuesday 8 October 13
  4. © 2013 innoQ Deutschland GmbH Multitude of potential service consumers

    Integration is ubiquitous CRM Application ERP Application Tuesday 8 October 13
  5. © 2013 innoQ Deutschland GmbH Multitude of potential service consumers

    Integration is ubiquitous CRM Application ? Tuesday 8 October 13
  6. © 2013 innoQ Deutschland GmbH Multitude of potential service consumers

    Integration is ubiquitous CRM Application Tuesday 8 October 13
  7. © 2013 innoQ Deutschland GmbH Patterns? Wasn’t there a book?

    Design Patterns (Gamma et al), 1994 Tuesday 8 October 13
  8. © 2013 innoQ Deutschland GmbH Patterns? Wasn’t there a book?

    Design Patterns (Gamma et al), 1994 Proven solutions for common problems Tuesday 8 October 13
  9. © 2013 innoQ Deutschland GmbH Patterns? Wasn’t there a book?

    Design Patterns (Gamma et al), 1994 Proven solutions for common problems Enterprise Integration Patterns (Hohpe & Woolf), 2003 Tuesday 8 October 13
  10. © 2013 innoQ Deutschland GmbH Patterns? Wasn’t there a book?

    Design Patterns (Gamma et al), 1994 Proven solutions for common problems Enterprise Integration Patterns (Hohpe & Woolf), 2003 Swiss-army knife for asynchronous messaging Tuesday 8 October 13
  11. © 2013 innoQ Deutschland GmbH Patterns? Wasn’t there a book?

    Design Patterns (Gamma et al), 1994 Proven solutions for common problems Enterprise Integration Patterns (Hohpe & Woolf), 2003 Swiss-army knife for asynchronous messaging www.eaipatterns.com Tuesday 8 October 13
  12. © 2013 innoQ Deutschland GmbH “We all believe that asynchronous

    messaging carries the greatest promise.” - Martin Fowler (Foreword of Enterprise Integration Patterns, 2003) Tuesday 8 October 13
  13. © 2013 innoQ Deutschland GmbH Benefits of async. Messaging decoupled

    integrated platforms/ languages Tuesday 8 October 13
  14. © 2013 innoQ Deutschland GmbH Benefits of async. Messaging decoupled

    integrated platforms/ languages reliable communication Tuesday 8 October 13
  15. © 2013 innoQ Deutschland GmbH Benefits of async. Messaging decoupled

    integrated platforms/ languages reliable communication disconnected Tuesday 8 October 13
  16. © 2013 innoQ Deutschland GmbH Benefits of async. Messaging decoupled

    integrated platforms/ languages reliable communication disconnected throttled Tuesday 8 October 13
  17. We take care of it - personally! © 2013 innoQ

    Deutschland GmbH But why those Patterns? Tuesday 8 October 13
  18. © 2013 innoQ Deutschland GmbH Thoughts on EAI patterns not

    invented, but observed Tuesday 8 October 13
  19. © 2013 innoQ Deutschland GmbH Thoughts on EAI patterns not

    invented, but observed don’t solve everything Tuesday 8 October 13
  20. © 2013 innoQ Deutschland GmbH Thoughts on EAI patterns not

    invented, but observed don’t solve everything provide ideas Tuesday 8 October 13
  21. © 2013 innoQ Deutschland GmbH Thoughts on EAI patterns not

    invented, but observed don’t solve everything provide ideas good ones evolve Tuesday 8 October 13
  22. © 2013 innoQ Deutschland GmbH Thoughts on EAI patterns not

    invented, but observed don’t solve everything provide ideas good ones evolve changes are incorporated at eaipatterns.com Tuesday 8 October 13
  23. © 2013 innoQ Deutschland GmbH Simple order management system (CRUD)

    Real Life Scenario order management system Tuesday 8 October 13
  24. © 2013 innoQ Deutschland GmbH Simple order management system (CRUD)

    Real Life Scenario order management system • basic Java EE Tuesday 8 October 13
  25. © 2013 innoQ Deutschland GmbH Simple order management system (CRUD)

    Real Life Scenario order management system • basic Java EE • Just CRUD operations Tuesday 8 October 13
  26. © 2013 innoQ Deutschland GmbH Simple order management system (CRUD)

    Real Life Scenario order management system • basic Java EE • Just CRUD operations • “information silo” Tuesday 8 October 13
  27. © 2013 innoQ Deutschland GmbH Simple order management system (CRUD)

    Real Life Scenario order management system • basic Java EE • Just CRUD operations • “information silo” Tuesday 8 October 13
  28. © 2013 innoQ Deutschland GmbH Enhance the system with an

    importer! Simple Change order management system Tuesday 8 October 13
  29. © 2013 innoQ Deutschland GmbH Enhance the system with an

    importer! Simple Change • Receive CSV-data via HTTP POST order management system Tuesday 8 October 13
  30. © 2013 innoQ Deutschland GmbH Enhance the system with an

    importer! Simple Change • Receive CSV-data via HTTP POST • CSV contains header and detail records order management system Tuesday 8 October 13
  31. © 2013 innoQ Deutschland GmbH Enhance the system with an

    importer! Simple Change • Receive CSV-data via HTTP POST • CSV contains header and detail records • Import data into database order management system Tuesday 8 October 13
  32. © 2013 innoQ Deutschland GmbH A Simple Java EE sample

    @WebServlet(urlPatterns = {"/order/import"}) public class ImporterServlet extends HttpServlet { @Inject OrderBean bean; @Inject CsvDataParser parser; @Override protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { String data = request.getParameter("csvdata"); List<Order> orders = parser.transform(data); for (Order order : orders) { bean.persist(order); } } } Tuesday 8 October 13
  33. © 2013 innoQ Deutschland GmbH Enhanced the system with an

    importer! System Simple Change done order management system HTTP csv Transform Business Partner Tuesday 8 October 13
  34. © 2013 innoQ Deutschland GmbH Integrate the system of a

    forwarder System Change happens order management system HTTP csv Transform Business Partner forwarder system FTP SMTP SOAP WSSE REST Tuesday 8 October 13
  35. © 2013 innoQ Deutschland GmbH Recognize an integration task when

    it‘s staring in your face? Tuesday 8 October 13
  36. © 2013 innoQ Deutschland GmbH Build an easy and maintainable

    solution for multiple integration challenges? Tuesday 8 October 13
  37. © 2013 innoQ Deutschland GmbH Something wrong here? @WebServlet(urlPatterns =

    {"/order/import"}) public class ImporterServlet extends HttpServlet { @Inject OrderBean bean; @Inject CsvDataParser parser; @Override protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { String data = request.getParameter("csvdata"); List<Order> orders = parser.transform(data); for (Order order : orders) { bean.persist(order); } } } Tuesday 8 October 13
  38. © 2013 innoQ Deutschland GmbH Something wrong here? @WebServlet(urlPatterns =

    {"/order/import"}) public class ImporterServlet extends HttpServlet { @Inject OrderBean bean; @Inject CsvDataParser parser; @Override protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { String data = request.getParameter("csvdata"); List<Order> orders = parser.transform(data); for (Order order : orders) { bean.persist(order); } } } testable? Tuesday 8 October 13
  39. © 2013 innoQ Deutschland GmbH Something wrong here? @WebServlet(urlPatterns =

    {"/order/import"}) public class ImporterServlet extends HttpServlet { @Inject OrderBean bean; @Inject CsvDataParser parser; @Override protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { String data = request.getParameter("csvdata"); List<Order> orders = parser.transform(data); for (Order order : orders) { bean.persist(order); } } } testable? reusable? Tuesday 8 October 13
  40. © 2013 innoQ Deutschland GmbH Something wrong here? @WebServlet(urlPatterns =

    {"/order/import"}) public class ImporterServlet extends HttpServlet { @Inject OrderBean bean; @Inject CsvDataParser parser; @Override protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { String data = request.getParameter("csvdata"); List<Order> orders = parser.transform(data); for (Order order : orders) { bean.persist(order); } } } testable? reusable? extensible? Tuesday 8 October 13
  41. © 2013 innoQ Deutschland GmbH Pipes and Filters divide your

    task into small steps http://www.enterpriseintegrationpatterns.com/PipesAndFilters.html Tuesday 8 October 13
  42. © 2013 innoQ Deutschland GmbH Route Pipe Apply pipes &

    filters pattern Pipe outbound transform inbound Tuesday 8 October 13
  43. © 2013 innoQ Deutschland GmbH Route Pipe Apply pipes &

    filters pattern Pipe outbound transform inbound Servlet Tuesday 8 October 13
  44. © 2013 innoQ Deutschland GmbH Route Pipe Apply pipes &

    filters pattern Pipe outbound transform inbound Servlet Custom Tuesday 8 October 13
  45. © 2013 innoQ Deutschland GmbH Route Pipe Apply pipes &

    filters pattern Pipe outbound transform inbound Servlet Custom JPA Tuesday 8 October 13
  46. © 2013 innoQ Deutschland GmbH When you got the right

    tools to do the job? Tuesday 8 October 13
  47. © 2013 innoQ Deutschland GmbH A simple camel route from("jetty:http://localhost:9080/order/import")

    .routeId(“orderimport”) .process(new PostParameterProcessor(“csvdata”)) .process(new StringRemover(new String[]{"\""})) .unmarshal().csv() .split(body(List.class)) .aggregate(header("orderId"), new MySpecialAggregationStrategy()).completionTimeout(3000) .to("seda:singlepartsroute"); Tuesday 8 October 13
  48. © 2013 innoQ Deutschland GmbH Spring Integration sample <int-http:inbound-channel-adapter !

    id="orderImportHttpAdapter" ! path="/order/import” supported-methods="POST" ! channel="ordersIn"/> <int:channel="ordersIn"/> <int:splitter input-channel="ordersIn" ref="orderSplitter" method="split" output-channel="ordersToDB" /> <bean id="orderSplitter" class="com.innoq.samples.eai.OrderSplitter"/> <int:channel="ordersToDB"/> <int-jpa:updating-outbound-gateway request-channel="ordersToDB" entity-class="com.innoq.samples.eai.domain.Order" entity-manager="em"/> Tuesday 8 October 13
  49. © 2013 innoQ Deutschland GmbH OracleDB + AQ Admin UI

    Real-life scenario: Control Bus xml-route-config EAI-Node EAI-Node EAI-Node ctrl-queue Tomcat Embedded Jetty Tuesday 8 October 13
  50. © 2013 innoQ Deutschland GmbH OracleDB + AQ Real-life scenario:

    Control Bus xml-route-config EAI-Node database connection EAI-Node EAI-Node ctrl-queue Initial Node configuration node type (command line arg) Admin UI Tuesday 8 October 13
  51. © 2013 innoQ Deutschland GmbH OracleDB + AQ Real-life scenario:

    Control Bus xml-route-config EAI-Node subscribe to control queue EAI-Node EAI-Node ctrl-queue 1. Server startup Admin UI Tuesday 8 October 13
  52. © 2013 innoQ Deutschland GmbH OracleDB + AQ Real-life scenario:

    Control Bus xml-route-config EAI-Node load node-type specific config EAI-Node EAI-Node ctrl-queue subscribe to control queue 1. Server startup Admin UI Tuesday 8 October 13
  53. © 2013 innoQ Deutschland GmbH OracleDB + AQ Config change

    @Runtime xml-route-config EAI-Node EAI-Node EAI-Node ctrl-queue 2. during runtime route config is changed Admin UI Tuesday 8 October 13
  54. © 2013 innoQ Deutschland GmbH OracleDB + AQ Config change

    @Runtime xml-route-config EAI-Node EAI-Node EAI-Node ctrl-queue 2. during runtime route config is changed publish config update message Admin UI Tuesday 8 October 13
  55. © 2013 innoQ Deutschland GmbH OracleDB + AQ Config change

    @Runtime xml-route-config EAI-Node interpret relevance of control message EAI-Node EAI-Node ctrl-queue 3. upon control message arrival Admin UI Tuesday 8 October 13
  56. © 2013 innoQ Deutschland GmbH OracleDB + AQ Config change

    @Runtime xml-route-config EAI-Node affected nodes reload configuration EAI-Node EAI-Node ctrl-queue interpret relevance of control message 3. upon control message arrival Admin UI Tuesday 8 October 13
  57. © 2013 innoQ Deutschland GmbH OracleDB + AQ Admin UI

    What would we change today? xml-route-config EAI-Node EAI-Node EAI-Node ctrl-queue GlassFish 4.0 Tuesday 8 October 13
  58. © 2013 innoQ Deutschland GmbH Message Router forward by condition

    http://www.enterpriseintegrationpatterns.com/MessageRouter.html Tuesday 8 October 13
  59. © 2013 innoQ Deutschland GmbH Message Router from(“ibmmq:QUEUE.IN“).noAutoStartup() .transacted() .policy(required)

    .routeId(BasicRouteBuilder.stdfromRouteId(this.componentBaseName)) .process(vslHeadersProcessor) .setHeader(HDR_DUMMYCOMPLCHK_IBR, constant(PASSEDMSG)) .bean(inboundTargetDispatcherBean) .wireTap("seda:inboundRouter.log"); Apache Camel running in WAS6.1 Tuesday 8 October 13
  60. © 2013 innoQ Deutschland GmbH Message Router from(“ibmmq:QUEUE.IN“).noAutoStartup() .transacted() .policy(required)

    .routeId(BasicRouteBuilder.stdfromRouteId(this.componentBaseName)) .process(vslHeadersProcessor) .setHeader(HDR_DUMMYCOMPLCHK_IBR, constant(PASSEDMSG)) .bean(inboundTargetDispatcherBean) .wireTap("seda:inboundRouter.log"); Apache Camel running in WAS6.1 Tuesday 8 October 13
  61. © 2013 innoQ Deutschland GmbH Message Router http://www.eaipatterns.com/MessageRouter.html public class

    InboundTargetMsgDispatcherBean implements Constants { /** * Map for all eligible Target Endpoints of the InboundRouter. */ private final Map<String, String[]> allTargets = new HashMap<String, String[]>(NROFROUTES); ... @RecipientList public String[] route(@Header(HDR_JMSX_GROUPID) String group) { String[] t = allTargets.get(group); return t; } /** * creates valid endpoint-uris from targetJMSUri and numbering. */ private void createAllTargets() { if (allTargets.keySet().size() == 0) { for (int i = 0; i < NROFROUTES; i++) { String target = createTargetJMSUri(i); allTargets.put(String.valueOf(i), new String[] { target }); } } } Tuesday 8 October 13
  62. © 2013 innoQ Deutschland GmbH Transformation für BPMN-System (2) from(“http://localhost:8080/authservice/proxy/transformed?bridgeEndpoint=true“)

    .routeId("bankapp.transformation.dispatch." + identification) .choice() .when().xpath("//v10:*[1]", inputNS) .to("direct:transform_v10_v11“) .otherwise() .to(outputEndpoint) .endChoice(); Tuesday 8 October 13
  63. © 2013 innoQ Deutschland GmbH Transformation für BPMN-System (2) from(“http://localhost:8080/authservice/proxy/transformed?bridgeEndpoint=true“)

    .routeId("bankapp.transformation.dispatch." + identification) .choice() .when().xpath("//v10:*[1]", inputNS) .to("direct:transform_v10_v11“) .otherwise() .to(“http://localhost:8380/routingservice/proxy/” + “BPMNSystemSpecEP?bridgeEndpoint=true“) .endChoice(); Tuesday 8 October 13
  64. © 2013 innoQ Deutschland GmbH Transformation für BPMN-System (2) from(“http://localhost:8080/authservice/proxy/transformed?bridgeEndpoint=true“)

    .routeId("bankapp.transformation.dispatch." + identification) .choice() .when().xpath("//v10:*[1]", inputNS) .to("direct:transform_v10_v11“) .otherwise() .to(“http://localhost:8380/routingservice/proxy/” + “BPMNSystemSpecEP?bridgeEndpoint=true“) .endChoice(); Tuesday 8 October 13
  65. © 2013 innoQ Deutschland GmbH Transformation für BPMN-System (2) from(“http://localhost:8080/authservice/proxy/transformed?bridgeEndpoint=true“)

    .routeId("bankapp.transformation.dispatch." + identification) .choice() .when().xpath("//v10:*[1]", inputNS) .to("direct:transform_v10_v11“) .otherwise() .to(“http://localhost:8380/routingservice/proxy/” + “BPMNSystemSpecEP?bridgeEndpoint=true“) .endChoice(); Tuesday 8 October 13
  66. © 2013 innoQ Deutschland GmbH Transformation für BPMN-System (3) from(“direct:transform_v10_v11“)

    .routeId("projectX.route.transformation.transform.v10_v11“) .setBody().xpath("/s:Envelope/s:Body/*[1]", soapNS) .to("xslt:xsl/BankX/Bank_v10_v11.xsl") .bean(XBankTransformerBean, "transform_v10_v11") .setBody().simple(TransformationConstants.soapStart +"$ {in.body}"+TransformationConstants.soapEnd) .process(new ContentPrinter("v10-v11“)) .inOut(“http://localhost:8380/routingservice/proxy/BPMNSystemSpecEP?“+ „bridgeEndpoint=true“) .to("direct:response" + reverseidentification); Tuesday 8 October 13
  67. © 2013 innoQ Deutschland GmbH Transformation für BPMN-System (3) from(“direct:transform_v10_v11“)

    .routeId("projectX.route.transformation.transform.v10_v11“) .setBody().xpath("/s:Envelope/s:Body/*[1]", soapNS) .to("xslt:xsl/BankX/Bank_v10_v11.xsl") .bean(XBankTransformerBean, "transform_v10_v11") .setBody().simple(TransformationConstants.soapStart +"$ {in.body}"+TransformationConstants.soapEnd) .process(new ContentPrinter("v10-v11“)) .inOut(outputEndpoint) .to("direct:response" + reverseidentification); Tuesday 8 October 13
  68. © 2013 innoQ Deutschland GmbH Transformation für BPMN-System (3) from(“direct:transform_v10_v11“)

    .routeId("projectX.route.transformation.transform.v10_v11“) .setBody().xpath("/s:Envelope/s:Body/*[1]", soapNS) .to("xslt:xsl/BankX/Bank_v10_v11.xsl") .bean(XBankTransformerBean, "transform_v10_v11") .setBody().simple(TransformationConstants.soapStart +"$ {in.body}"+TransformationConstants.soapEnd) .process(new ContentPrinter("v10-v11“)) .inOut(outputEndpoint) .to("direct:response" + reverseidentification); Tuesday 8 October 13
  69. © 2013 innoQ Deutschland GmbH Transformation für BPMN-System (3) from(“direct:transform_v10_v11“)

    .routeId("projectX.route.transformation.transform.v10_v11“) .setBody().xpath("/s:Envelope/s:Body/*[1]", soapNS) .to("xslt:xsl/BankX/Bank_v10_v11.xsl") .bean(XBankTransformerBean, "transform_v10_v11") .setBody().simple(TransformationConstants.soapStart +"$ {in.body}"+TransformationConstants.soapEnd) .process(new ContentPrinter("v10-v11“)) .inOut(outputEndpoint) .to("direct:response" + reverseidentification); Tuesday 8 October 13
  70. © 2013 innoQ Deutschland GmbH Transformation für BPMN-System (3) from("direct:transform_v10_v11")

    .routeId("projectX.route.transformation.transform." + identification) .setBody().xpath("/s:Envelope/s:Body/*[1]", soapNS) .to("xslt:xsl/BankX/Bank_" + identification + ".xsl") .bean(transformerBean, "transform_v10_v11") ... public class BankTransformerBean extends AbstractTransformerBean { @SuppressWarnings({ "rawtypes" }) public String transform_v10_v11(@Body String body) throws JDOMException, IOException { Element message = parse(body); message.removeNamespaceDeclaration(nsXBANK_v1_0); message.removeNamespaceDeclaration(nsYBANK_v1_0); message.addNamespaceDeclaration(nsXBANKv1_1); .... return toString(message); } @SuppressWarnings({ "rawtypes" }) public String transform_v11_v10(@Body String body) throws JDOMException, IOException { Tuesday 8 October 13
  71. © 2013 innoQ Deutschland GmbH Transformation für BPMN-System (3) from(“direct:transform_v10_v11“)

    .routeId("projectX.route.transformation.transform.v10_v11“) .setBody().xpath("/s:Envelope/s:Body/*[1]", soapNS) .to("xslt:xsl/BankX/Bank_v10_v11.xsl") .bean(XBankTransformerBean, "transform_v10_v11") .setBody().simple(TransformationConstants.soapStart +"$ {in.body}"+TransformationConstants.soapEnd) .process(new ContentPrinter("v10-v11“)) .inOut(“http://localhost:8380/routingservice/proxy/BPMNSystemSpecEP?“+ „bridgeEndpoint=true“) .to("direct:response_v11_v10“); Tuesday 8 October 13
  72. © 2013 innoQ Deutschland GmbH Transformation für BPMN-System (3) from(“direct:transform_v10_v11“)

    .routeId("projectX.route.transformation.transform.v10_v11“) .setBody().xpath("/s:Envelope/s:Body/*[1]", soapNS) .to("xslt:xsl/BankX/Bank_v10_v11.xsl") .bean(XBankTransformerBean, "transform_v10_v11") .setBody().simple(TransformationConstants.soapStart +"$ {in.body}"+TransformationConstants.soapEnd) .process(new ContentPrinter("v10-v11“)) .inOut(“http://localhost:8380/routingservice/proxy/BPMNSystemSpecEP?“+ „bridgeEndpoint=true“) .to("direct:response_v11_v10“); Tuesday 8 October 13
  73. © 2013 innoQ Deutschland GmbH Transformation für BPMN-System (4) from("direct:response_v11_v10“)

    .setBody().xpath("/s:Envelope/s:Body/*[1]", soapNS) .to("xslt:xsl/BankX/Bank_v11_v10.xsl") .bean(transformerBean, "transform_v11_v10") .setBody().simple(TransformationConstants.soapStartTixBank +"${in.body}" +TransformationConstants.soapEnd); Tuesday 8 October 13
  74. © 2013 innoQ Deutschland GmbH Route Pipe Flexibility through Filters

    Pipe outbound filter inbound Filters are exchangeable, reusable and easily testable Tuesday 8 October 13
  75. © 2013 innoQ Deutschland GmbH Should I always use an

    EAI-Framework? Tuesday 8 October 13
  76. © 2013 innoQ Deutschland GmbH Should I always use an

    EAI-Framework? It depends! Tuesday 8 October 13
  77. © 2013 innoQ Deutschland GmbH Further tips considering EAI small

    building blocks no shared mutable state Tuesday 8 October 13
  78. © 2013 innoQ Deutschland GmbH Further tips considering EAI small

    building blocks no shared mutable state use immutable DTOs Tuesday 8 October 13
  79. © 2013 innoQ Deutschland GmbH Further tips considering EAI small

    building blocks no shared mutable state use immutable DTOs => increased scalability Tuesday 8 October 13
  80. © 2013 innoQ Deutschland GmbH Further tips considering EAI small

    building blocks no shared mutable state use immutable DTOs => increased scalability advanced: see “SEDA” & “actor model” Tuesday 8 October 13
  81. We take care of it - personally! © 2013 innoQ

    Deutschland GmbH Alexander Heusingfeld, @goldstift [email protected] Martin Huber, @waterback [email protected] http://www.innoq.com/de/talks Vielen Dank! Tuesday 8 October 13