设为首页 收藏本站
查看: 654|回复: 0

[经验分享] Apache Camel 让“集成”不再是梦魇

[复制链接]

尚未签到

发表于 2018-11-27 08:43:20 | 显示全部楼层 |阅读模式
  很久很久以前,不知道有21种设计模式,代码Review的时候被Challenge无数次;当我费尽周折做完一个集成项目后,发现原来有更好的企业集成设计模式。也许人生就是经历些曲折,没试过“集成”的苦,又怎能体会设计模式的必要。Apache Camel官方推荐的入门文章:http://architects.dzone.com/articles/apache-camel-integration。
  Take any integration project and you have multiple applications talking over multiple transports on multiple platforms. As you can imagine, in large enterprise applications this can get complex very fast. Much of the complexity stems from two issues:
  1.    dealing with the specifics of applications and transports, and
  2.    coming up with good solutions to integration problems.

  Making your applications speak transports and APIs is>  Ignoring the mechanics of how to connect with multiple transports and APIs, we can focus on the high level design of how applications interact. Fortunately, most solutions to enterprise integration problems have been formalized already. Gregor Hohpe and Bobby Woolfe's book, Enterprise Integration Patterns: Designing, Building, and Deploying Messaging Solutions, boils down years of experience from enterprise architects into a set of sixty five Enterprise Integration Patterns (EIPs). This is great but we still have to hand code all parts of these patterns; these are not packaged solutions, only recommendations.
  Apache Camel was created with the intention of addressing these two issues. In this article I'll show you how it actually does this.
  What is Camel?
  Apache Camel is an open source Java framework that focuses on making integration easier and more accessible to developers. It does this by providing:
  ?    concrete implementations of all the widely used EIPs
  ?    connectivity to a great variety of transports and APIs
  ?    easy to use Domain Specific Language (DSL) to wire EIPs and transports together
  Figure 1 shows how these three items actually map to Camel concepts. To give you a good understanding of how Camel is organized, we will discuss Components, Endpoints, Processors, and the Domain Specific Language (DSL). There is of course a lot more going on here under the hood but we'll leave that for another discussion.
DSC0000.jpg

  Figure 1: High level view of Camel's architecture.
  Components are the extension point in Camel to add connectivity to other systems. The core of Camel is very small to keep dependencies low, promote embeddability, etc. and as a result contains only 12 essential components. There are over 60 components outside the core. To expose these systems to the rest of Camel, Components provide an Endpoint interface. By using URIs, you can send or receive messages on Endpoints in a uniform way. For instance, to receive messages from a JMS queue aQueue and send them to a file system directory "c:/tmp", you could use URIs like "jms:aQueue" and "file:c:\tmp".
  Processors are used to manipulate and mediate messages in between Endpoints. All of the EIPs are defined as Processors or sets of Processors. As of writing, Camel supports 41 patterns from the EIP book, 6 other integration patterns, and many other useful Processors.
  To wire Processors and Endpoints together, Camel defines a Java DSL. The term DSL is used a bit loosely here as it usually implies the involvement of a compiler or interpreter that can process keywords specific to a particular domain. In Camel, DSL means a fluent Java API that contains methods named like terms from the EIP book. Its best explained with an example
  1.from("jms:aQueue")
  2..filter().xpath("/person[@name='Jon']")
  3..to("file:c:\tmp");
  Here we define a routing rule in a single Java statement that will consume messages from the "jms:aQueue" Endpoint, send them through a Message Filter Processor, which will then send on messages passing the XPath condition to the "file:c:\tmp" endpoint. Messages failing the condition will be dropped.
  You can also configure your routes in a XML-based Spring configuration file. This configuration file is a lot more verbose and less auto complete friendly than the Java DSL; many prefer it though because of its direct access to Spring concepts and no requirement for compilation after changes. Here is what the earlier example would look like in Spring:
  01.
  02.
  03.
  04.
  05./person[@name='Jon']
  06.
  07.
  08.
  09.
  These are the concepts that Camel was built upon. Since then many other interesting features have been added. Details of these are left up to the reader to investigate. To get you started, some of these include:
  ?    Pluggable data formats and type converters for easy message transformation between Artix Data Services, CSV, EDI, Flatpack, HL7, JAXB, JSON, XmlBeans, XStream, Zip, Camel-bindy, etc.
  ?    Pluggable languages to create expressions or predicates for use in the DSL. Some of these languages include: EL, JXPath, Mvel, OGNL, BeanShell, JavaScript, Groovy, Python, PHP, Ruby, SQL, XPath, XQuery, etc.
  ?    Support for the integration of beans and POJOs in various places in Camel.
  ?    Excellent support for testing distributed and asynchronous systems using a messaging approach
  ?    and much more...
  Example
  A motorcycle parts business, Rider Auto Parts, supplies parts to motorcycle manufacturers. Over the years they've changed the way they receive orders several times. Initially, orders were placed by uploading CSV files to an FTP server. The message format was later changed to XML. Currently they provide a web site to submit orders as XML messages over HTTP. All of these messages are converted to an internal POJO format before processing.
  Rider Auto Parts states to any new customers to use the web interface to place orders. However, because of existing agreements with customers, they must keep all the old message formats and interfaces up and running.
  Solution using EIPs

  Rider Auto Parts>
DSC0001.jpg

  Figure 2: This shows the solution to Rider Auto Parts integration problem using notation from the Enterprise Integration Patterns book.
  So we have several patterns in use here.
  1. There are two Message Endpoints; one for FTP connectivity and another for HTTP.
  2. Messages from these endpoints are fed into the incomingOrderQueue Message Channel
  3. The messages are consumed from the incomingOrderQueue and routed by a Content-Based Router to one of two Message Translators. As the EIP name implies, the routing destination depends on the content of the message. In this case we need to route based on whether the content is a CSV or XML file.
  4. Both Message Translators convert the message content into a POJO, which is fed into the orderQueue Message Channel.
  The whole section that uses a Content-Based Router and several Message Translators is referred to as a Normalizer. This composite pattern has a unique graphic to depict it but was left out here in favor of its sub-patterns to make things clearer.
  Implementation using Camel
  As mentioned before, Camel has a small core set of components included by default. The rest of the components exist as separate modules. In applications that require many types of connectivity it is useful to figure out what Camel modules to include. Listing 1 shows the dependencies using Apache Maven for the Camel implementation of the Rider Auto Parts example. Of course, you don't need to use Apache Maven for dependencies - it is just the easiest way to rapidly add new dependencies to your applications. The list of dependencies includes support for core Camel, ActiveMQ, JAXB marshaling, CSV marshaling, and HTTP. To make the example easier to try out, I've opted to use the File endpoint instead of the FTP. If we were using the FTP endpoint we would need to add a dependency on the camel-ftp module as well.
  Listing 1: Maven dependencies for the Camel implementation
  01.
  02.
  03.
  04.org.apache.camel
  05.camel-core
  06.${camel-version}
  07.
  08.
  09.org.apache.camel
  10.camel-spring
  11.${camel-version}
  12.
  13.
  14.
  15.
  16.org.apache.activemq
  17.activemq-camel
  18.${activemq-version}
  19.
  20.
  21.
  22.
  23.org.apache.camel
  24.camel-jaxb
  25.${camel-version}
  26.
  27.
  28.
  29.
  30.org.apache.camel
  31.camel-csv
  32.${camel-version}
  33.
  34.
  35.
  36.
  37.org.apache.camel
  38.camel-jetty
  39.${camel-version}
  40.
  41.
  42.
  43.
  44.org.apache.activemq
  45.activemq-core
  46.${activemq-version}
  47.
  48.
  49.org.apache.xbean
  50.xbean-spring
  51.${xbean-spring-version}
  52.
  53.

  While it is perfectly legitimate to use Camel as a standalone Java application, it is often useful to embed it in a container. In this case, we will be loading Camel from Spring. The Spring beans XML file is shown in Listing 2. First we start an embedded Apache ActiveMQ broker and connect Camel to it. We also load up some helper beans that we will reference from the DSL. Finally, the camelContext element tells Camel to look for routes in the org.fusesource.camel package. Routes are Java>  Listing 2: Spring XML file that configures an embedded ActiveMQ broker, several beans used in the Camel route, and initializes the Camel Context to search for routes in the org.fusesource.camel package.
  view source
  print?
  01.
  10.
  11.
  12.
  13.
  14.
  15.
  16.

  17.  18.
  19.
  20.

  21.
  22.  23.
  24.
  25.org.fusesource.camel
  26.
  27.
  28.

  The real meat of the Camel implementation lies in the OrderRouter>  Looking back at Figure 2, we need to receive orders from an FTP (substituted with File) and HTTP endpoint, formatted as shown in Listing 4. In the DSL we can specify these incoming endpoints with two from elements. Both from elements are connected to a to("jms:incomingOrderQueue") element, which will send the messages to a queue on the ActiveMQ broker.
  Listing 3: Route definitions for the example. The routing rules are specified using a fluent API, referred to as Camel's DSL.
  view source
  print?

  01.public>  02.
  03.@Override
  04.public void configure() throws Exception {
  05.JaxbDataFormat jaxb = new JaxbDataFormat("org.fusesource.camel");
  06.
  07.// Receive orders from two endpoints
  08.from("file:src/data?noop=true").to("jms:incomingOrderQueue");
  09.from("jetty:http://localhost:8888/placeorder")
  10..inOnly().to("jms:incomingOrderQueue")
  11..transform().constant("OK");
  12.
  13.// Do the normalization
  14.from("jms:incomingOrderQueue")
  15..convertBodyTo(String.class)
  16..choice()
  17..when().method("orderHelper", "isXml")
  18..unmarshal(jaxb)
  19..to("jms:orderQueue")
  20..when().method("orderHelper", "isCsv")
  21..unmarshal().csv()
  22..to("bean:normalizer")
  23..to("jms:orderQueue");
  24.}
  25.
  26.}
  In the case of the HTTP endpoint, there are a couple of extra things to mention. First off the HTTP client will be expecting a response from the application so we have to handle that. In Camel, we have full control over what the client gets back from the HTTP endpoint. Each response is determined by the last method in our current route definition (each Java statement is a route definition). In our case we use the transform method to set the response to the constant string "OK". Since we handle the response ourselves, we don’t want any response to come from the JMS incomingOrderQueue. To send to this queue in a fire-and-forget fashion we add the inOnly modifier.

  It is important to note at this point that when writing Camel DSL in a modern Java>  Listing 4: Incoming message formats; XML on top, CSV below.
  1.
  2.
  3.
  4."name", "amount"
  5."brake pad", "2"
  The next section of DSL in Listing 3 specifies the Normalizer, complete with Content-Based Router and two Message Translators. First we specify that we want to consume messages from the incomingOrderQueue on the ActiveMQ broker. The content based routing of the messages is done with the choice and when methods. In our case, we want to send CSV messages to one Message Translator and XML messages to another. To check what type of message we have we will be using a simple Java bean shown in Listing 5. Of course, this is demonstration code only; for production cases you would want to add more thorough checking of content types.
  Listing 5: Java bean that contains helper methods to be used in the DSL.

  01.public>  02.public boolean isCsv(String body) {
  03.return !body.contains("  01.@XmlRootElement
  02.@XmlAccessorType(XmlAccessType.FIELD)

  03.public>  04.@XmlAttribute
  05.private String name;
  06.@XmlAttribute
  07.private int amount;
  08.
  09.public Order() {
  10.}
  11.
  12.public Order(String name, int amount) {
  13.this.name = name;
  14.this.amount = amount;
  15.}
  16.
  17.@Override
  18.public String toString() {
  19.return "Order[" + name + " , " + amount + "]";
  20.}
  21.}
  For the transformation from CSV to Order object, we don't have a nice JAXB analogue. We do have support in Camel for unmarhsaling CSV content into a List though. We use this in combination with a custom bean to do the complete transformation. The OrderNormalizer bean shown in Listing 7 takes the List of Lists created by the CSV unmarshaler and creates a new Order object from it.
  Listing 7: Java bean that takes the CSV data and creates a new Order domain object from it.

  1.public>  2.public Order fromCsvToOrder(List<List<String>> body) {
  3.List orderHeaders = body.get(0);
  4.List orderValues = body.get(1);
  5.return new Order(orderValues.get(0), Integer.parseInt(orderValues.get(1)));
  6.}
  7.}
  At this point, successfully normalized messages are sent to the orderQueue for processing by some other application at the Rider Auto Parts business.
  Conclusion

  In this article I've shown two common problems that an integration developer may>  Links

  • Apache Camel – http://camel.apache.org
  • FUSE Mediation Router (based on Apache Camel) – http://fusesource.com/products/enterprise-camel
  • Enterprise Integration Patterns – http://www.enterpriseintegrationpatterns.com
  • Jon’s Blog – http://janstey.blogspot.com
  • Camel in Action book - http://www.manning.com/ibsen
  • Article source code - http://repo.fusesource.com/maven2/org/fusesource/examples/rider-auto-example/1.0/rider-auto-example-1.0.zip


运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-640086-1-1.html 上篇帖子: linux下apache+php安装常见问题 下篇帖子: 使用 Apache Axis 和 Castor 创建 Web 服务
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表