续上篇介绍了第十三个ESB应用,本文介绍第十四个ESB应用——Transform XML to POJO。
说明:本文及后续文章虽非百分百的原创,但毕竟包含本人的努力和付出,所以希望大家转载时务请注明出处:http://yarafa.iteye.com/,谢谢合作。
1 概述
本实例主要演示了如何通过配置Smooks将一个XML文件转换成POJO。
2 新建ESB工程
操作过程略。
3 ESB配置
3.1 创建消息队列
<?xml version="1.0" encoding="UTF-8"?> <server> <mbean code="org.jboss.jms.server.destination.QueueService" name="jboss.esb.quickstart.destination:service=Queue,name=transformpojoGw" xmbean-dd="xmdesc/Queue-xmbean.xml"> <depends optional-attribute-name="ServerPeer"> jboss.messaging:service=ServerPeer </depends> <depends>jboss.messaging:service=PostOffice</depends> </mbean> <mbean code="org.jboss.jms.server.destination.QueueService" name="jboss.esb.quickstart.destination:service=Queue,name=transformpojoEsb" xmbean-dd="xmdesc/Queue-xmbean.xml"> <depends optional-attribute-name="ServerPeer"> jboss.messaging:service=ServerPeer </depends> <depends>jboss.messaging:service=PostOffice</depends> </mbean> <mbean code="org.jboss.jms.server.destination.QueueService" name="jboss.esb.quickstart.destination:service=Queue,name=transformpojoResponse" xmbean-dd="xmdesc/Queue-xmbean.xml"> <depends optional-attribute-name="ServerPeer"> jboss.messaging:service=ServerPeer </depends> <depends>jboss.messaging:service=PostOffice</depends> </mbean> </server>
3.2 定义Provider
这里将定义一个JMS Provider,并定义2个消息通道,内容如下:
<jms-provider connection-factory="ConnectionFactory" name="JBossMQ"> <jms-bus busid="gwChanel"> <jms-message-filter dest-name="queue/transformpojoGw" dest-type="QUEUE" /> </jms-bus> <jms-bus busid="esbChanel"> <jms-message-filter dest-name="queue/transformpojoEsb" dest-type="QUEUE" /> </jms-bus> </jms-provider>
3.3 定义Java Bean
3.3.1 Customer
package com.thu.afa.esb.jbossesb.bean;
import java.io.Serializable;
public class Customer implements Serializable
{
private static final long serialVersionUID = 1L;
private String userName;
private String firstName;
private String lastName;
private String state;
/**
* @return Returns the firstName.
*/
public String getFirstName()
{
return firstName;
}
/**
* @param firstName
* The firstName to set.
*/
public void setFirstName(String firstName)
{
// System.out.println("**** firstName: " + firstName);
this.firstName = firstName;
}
/**
* @return Returns the lastName.
*/
public String getLastName()
{
return lastName;
}
/**
* @param lastName
* The lastName to set.
*/
public void setLastName(String lastName)
{
this.lastName = lastName;
}
/**
* @return Returns the state.
*/
public String getState()
{
return state;
}
/**
* @param state
* The state to set.
*/
public void setState(String state)
{
this.state = state;
}
/**
* @return Returns the userName.
*/
public String getUserName()
{
return userName;
}
/**
* @param userName
* The userName to set.
*/
public void setUserName(String userName)
{
this.userName = userName;
}
/*
* (non-Javadoc)
*
* @see java.lang.Object#toString()
*/
@Override
public String toString()
{
return userName + "," + firstName + "," + lastName + "," + state;
}
}
3.3.2 OrderHeader
package com.thu.afa.esb.jbossesb.bean;
import java.util.Calendar;
import java.text.SimpleDateFormat;
import java.io.Serializable;
public class OrderHeader implements Serializable
{
private static final long serialVersionUID = 1L;
private String orderId;
private Calendar orderDate;
private int statusCode;
private double netAmount;
private double totalAmount;
private double tax;
/**
* @return Returns the netAmount.
*/
public double getNetAmount()
{
return netAmount;
}
/**
* @param netAmount
* The netAmount to set.
*/
public void setNetAmount(double netAmount)
{
this.netAmount = netAmount;
}
/**
* @return Returns the orderDate.
*/
public Calendar getOrderDate()
{
return orderDate;
}
/**
* @param orderDate
* The orderDate to set.
*/
public void setOrderDate(Calendar orderDate)
{
this.orderDate = orderDate;
}
/**
* @return Returns the orderId.
*/
public String getOrderId()
{
return orderId;
}
/**
* @param orderId
* The orderId to set.
*/
public void setOrderId(String orderId)
{
this.orderId = orderId;
}
/**
* @return Returns the statusCode.
*/
public int getStatusCode()
{
return statusCode;
}
/**
* @param statusCode
* The statusCode to set.
*/
public void setStatusCode(int statusCode)
{
this.statusCode = statusCode;
}
/**
* @return Returns the tax.
*/
public double getTax()
{
return tax;
}
/**
* @param tax
* The tax to set.
*/
public void setTax(double tax)
{
this.tax = tax;
}
/**
* @return Returns the totalAmount.
*/
public double getTotalAmount()
{
return totalAmount;
}
/**
* @param totalAmount
* The totalAmount to set.
*/
public void setTotalAmount(double totalAmount)
{
this.totalAmount = totalAmount;
}
private SimpleDateFormat dateFormat = new SimpleDateFormat("d-MMM-yyyy");
/*
* (non-Javadoc)
*
* @see java.lang.Object#toString()
*/
@Override
public String toString()
{
return orderId
+ ", "
+ (orderDate == null ? null : dateFormat.format(orderDate
.getTime())) + ", " + statusCode + ", " + netAmount
+ ", " + totalAmount + ", " + tax + ", ";
}
}
3.3.3 OrderItem
package com.thu.afa.esb.jbossesb.bean;
import java.io.Serializable;
public class OrderItem implements Serializable
{
private static final long serialVersionUID = 1L;
private int position;
private int quantity;
private String productId;
private String title;
private double price;
/**
* @return Returns the position.
*/
public int getPosition()
{
return position;
}
/**
* @param position
* The position to set.
*/
public void setPosition(int position)
{
// System.out.println("**** position: " + position);
this.position = position;
}
/**
* @return Returns the price.
*/
public double getPrice()
{
return price;
}
/**
* @param price
* The price to set.
*/
public void setPrice(double price)
{
// System.out.println("**** price: " + price);
this.price = price;
}
/**
* @return Returns the productId.
*/
public String getProductId()
{
return productId;
}
/**
* @param productId
* The productId to set.
*/
public void setProductId(String productId)
{
this.productId = productId;
}
/**
* @return Returns the quantity.
*/
public int getQuantity()
{
return quantity;
}
/**
* @param quantity
* The quantity to set.
*/
public void setQuantity(int quantity)
{
this.quantity = quantity;
}
/**
* @return Returns the title.
*/
public String getTitle()
{
return title;
}
/**
* @param title
* The title to set.
*/
public void setTitle(String title)
{
this.title = title;
}
/*
* (non-Javadoc)
*
* @see java.lang.Object#toString()
*/
@Override
public String toString()
{
return position + "," + quantity + "," + productId + "," + title + ","
+ price;
}
}
3.4 定义转换映射文件
在src目录下新建文件smooks-res.xml,内容如下:
<?xml version='1.0' encoding='UTF-8'?> <smooks-resource-list xmlns="http://www.milyn.org/xsd/smooks-1.1.xsd" xmlns:jb="http://www.milyn.org/xsd/smooks/javabean-1.2.xsd"> <!-- Populate the OrderHeader --> <jb:bean beanId="orderHeader" class="com.thu.afa.esb.jbossesb.bean.OrderHeader" createOnElement="order"> <jb:value property="orderId" data="Order/@orderId" /> <jb:value property="orderDate" data="Order/@orderDate" decoder="Calendar"> <jb:decodeParam name="format">EEE MMM dd HH:mm:ss z yyyy</jb:decodeParam> <jb:decodeParam name="locale-language">en</jb:decodeParam> <jb:decodeParam name="locale-country">US</jb:decodeParam> </jb:value> <jb:value property="statusCode" data="Order/@statusCode" /> <jb:value property="netAmount" data="Order/@netAmount" /> <jb:value property="totalAmount" data="Order/@totalAmount" /> <jb:value property="tax" data="Order/@tax" /> </jb:bean> <!-- Populate the Customer --> <jb:bean beanId="customer" class="com.thu.afa.esb.jbossesb.bean.Customer" createOnElement="customer"> <jb:value property="userName" data="customer/@userName" /> <jb:value property="firstName" data="customer/@firstName" /> <jb:value property="lastName" data="customer/@lastName" /> <jb:value property="state" data="customer/@state" /> </jb:bean> <!-- Populate the OrderItem list --> <jb:bean beanId="orderItemList" class="java.util.ArrayList" createOnElement="orderlines"> <jb:wiring beanIdRef="orderItem" /> </jb:bean> <!-- Populate the OrderItem instance --> <jb:bean beanId="orderItem" class="com.thu.afa.esb.jbossesb.bean.OrderItem" createOnElement="orderlines/orderline"> <jb:value property="position" data="orderline/@position" /> <jb:value property="quantity" data="orderline/@quantity" /> <jb:value property="productId" data="orderline/product/@productId" /> <jb:value property="title" data="orderline/product/@title" /> <jb:value property="price" data="orderline/product/@price" /> </jb:bean> </smooks-resource-list>
3.4 定义Service
<service category="Transform" description="Transform" name="TransformService"> <listeners /> <actions mep="OneWay" /> </service>
3.5 定义Listener
<listeners> <jms-listener busidref="gwChanel" is-gateway="true" name="gwListener" /> <jms-listener busidref="esbChanel" name="esbListener" /> </listeners>
3.6 定义Action类
3.6.1 ReturnJMSMessage
/***********************************************************************
* <p>Project Name: transformxml2pojo</p>
* <p>File Name: com.thu.afa.esb.jbossesb.action.ReturnJMSMessage.java</p>
* <p>Copyright: Copyright (c) 2010</p>
* <p>Company: <a href="http://afa.thu.com">http://afa.thu.com</a></p>
***********************************************************************/
package com.thu.afa.esb.jbossesb.action;
import java.util.Hashtable;
import javax.jms.Queue;
import javax.jms.QueueConnection;
import javax.jms.QueueConnectionFactory;
import javax.jms.QueueSender;
import javax.jms.QueueSession;
import javax.jms.TextMessage;
import javax.naming.Context;
import javax.naming.InitialContext;
import org.jboss.soa.esb.addressing.eprs.JMSEpr;
import org.jboss.soa.esb.helpers.ConfigTree;
import org.jboss.soa.esb.message.Message;
/**
* <p>Class Name: ReturnJMSMessage</p>
* <p>Description: </p>
* @author Afa
* @date 2010-9-17
* @version 1.0
*/
public class ReturnJMSMessage
{
public static void sendMessage(Message esbMessage, String destination,
ConfigTree config) throws Exception
{
if (esbMessage == null || destination == null)
throw new Exception("Message and JMS Destination are required");
QueueConnection connection;
QueueSession session;
Queue queue;
final Hashtable<String, String> env = new Hashtable<String, String>();
final String providerURL = config.getAttribute(JMSEpr.JNDI_URL_TAG);
if (providerURL != null)
{
env.put(Context.PROVIDER_URL, providerURL);
}
final String contextFactory = config.getAttribute(JMSEpr.JNDI_CONTEXT_FACTORY_TAG);
if (contextFactory != null)
{
env.put(Context.INITIAL_CONTEXT_FACTORY, contextFactory);
}
final String urlPkgPrefixes = config.getAttribute(JMSEpr.JNDI_PKG_PREFIX_TAG);
if (urlPkgPrefixes != null)
{
env.put(Context.URL_PKG_PREFIXES, urlPkgPrefixes);
}
InitialContext context = new InitialContext(env);
QueueConnectionFactory factory = (QueueConnectionFactory) context.lookup("ConnectionFactory");
connection = factory.createQueueConnection();
queue = (Queue) context.lookup("queue/" + destination);
session = connection.createQueueSession(false, QueueSession.AUTO_ACKNOWLEDGE);
connection.start();
String message = (String) esbMessage.getBody().get();
QueueSender send = session.createSender(queue);
TextMessage textMessage = session.createTextMessage(message);
send.send(textMessage);
connection.stop();
}
}
3.6.2 MyJMSListenerAction
/***********************************************************************
* <p>Project Name: transformxml2pojo</p>
* <p>File Name: com.thu.afa.esb.jbossesb.action.MyJMSListenerAction.java</p>
* <p>Copyright: Copyright (c) 2010</p>
* <p>Company: <a href="http://afa.thu.com">http://afa.thu.com</a></p>
***********************************************************************/
package com.thu.afa.esb.jbossesb.action;
import org.jboss.soa.esb.actions.AbstractActionLifecycle;
import org.jboss.soa.esb.helpers.ConfigTree;
import org.jboss.soa.esb.message.Body;
import org.jboss.soa.esb.message.Message;
/**
* <p>Class Name: MyJMSListenerAction</p>
* <p>Description: </p>
* @author Afa
* @date 2010-9-17
* @version 1.0
*/
public class MyJMSListenerAction extends AbstractActionLifecycle
{
protected ConfigTree configTree;
public MyJMSListenerAction(ConfigTree configTree)
{
this.configTree = configTree;
}
public Message displayMessage(Message message) throws Exception
{
System.out.println("******* Display Message ********");
System.out.println(message.getBody().get());
return message;
}
public Message playWithMessage(Message message) throws Exception
{
Body body = message.getBody();
String content = (String) body.get();
StringBuffer buffer = new StringBuffer();
buffer.append("********* Before *********");
buffer.append(content);
buffer.append("********* After *********");
body.add(buffer.toString());
return message;
}
public Message sendResponse(Message message) throws Exception
{
ReturnJMSMessage.sendMessage(message, "transformpojoResponse", configTree);
return message;
}
public void exceptionHandler(Message message, Throwable exception)
{
System.out.println("!ERROR!");
System.out.println(exception.getMessage());
System.out.println("For Message: ");
System.out.println(message.getBody().get());
}
}
3.6.3 DVDStoreAction
/***********************************************************************
* <p>Project Name: transformxml2pojo</p>
* <p>File Name: com.thu.afa.esb.jbossesb.action.DVDStoreAction.java</p>
* <p>Copyright: Copyright (c) 2010</p>
* <p>Company: <a href="http://afa.thu.com">http://afa.thu.com</a></p>
***********************************************************************/
package com.thu.afa.esb.jbossesb.action;
import java.util.List;
import java.util.Map;
import org.jboss.soa.esb.actions.AbstractActionLifecycle;
import org.jboss.soa.esb.helpers.ConfigTree;
import org.jboss.soa.esb.message.Message;
import com.thu.afa.esb.jbossesb.bean.Customer;
import com.thu.afa.esb.jbossesb.bean.OrderHeader;
/**
* <p>Class Name: DVDStoreAction</p>
* <p>Description: </p>
* @author Afa
* @date 2010-9-17
* @version 1.0
*/
public class DVDStoreAction extends AbstractActionLifecycle
{
protected ConfigTree configTree;
public DVDStoreAction(ConfigTree configTree)
{
this.configTree = configTree;
}
@SuppressWarnings("unchecked")
public Message process(Message message) throws Exception
{
StringBuffer results = new StringBuffer();
Map<String, Object> map = (Map<String, Object>) message.getBody().get();
OrderHeader header = (OrderHeader) map.get("orderHeader");
Customer customer = (Customer) map.get("customer");
List orderItems = (List) map.get("orderItemList");
results.append("Demonstrates Smooks ability to rip the XML into Objects\n");
results.append("********* DVDStoreAction - Order Value Objects Populated *********\n");
results.append("Header: " + header + "\n");
results.append("Customer: " + customer + "\n");
if (orderItems != null)
{
results.append("Order Items (" + orderItems.size() + "):\n");
for (int i = 0; i < orderItems.size(); i++)
{
results.append("\t" + i + ": " + orderItems.get(i) + "\n");
}
}
results.append("\n****************************************************************** ");
message.getBody().add(results.toString());
return message;
}
}
3.7 配置Action
<actions mep="OneWay"> <action name="printBefore" process="displayMessage" class="com.thu.afa.esb.jbossesb.action.MyJMSListenerAction" /> <action class="org.jboss.soa.esb.smooks.SmooksAction" name="transform"> <property name="smooksConfig" value="/smooks-res.xml" /> <property name="resultType" value="JAVA" /> </action> <action class="com.thu.afa.esb.jbossesb.action.DVDStoreAction" name="convertPOJO2Message" process="process" /> <action name="printAfter" process="displayMessage" class="com.thu.afa.esb.jbossesb.action.MyJMSListenerAction" /> <action name="returnToSender" process="sendResponse" class="com.thu.afa.esb.jbossesb.action.MyJMSListenerAction" /> <action class="org.jboss.soa.esb.actions.SystemPrintln" name="print"> <property name="message" value=">>>> Message after Smooks intermediate xml -> target pojos :" /> </action> </actions>
3.8 配置部署文件
部署依赖文件deployment.xml内容如下:
<jbossesb-deployment> <depends>jboss.esb:deployment=smooks.esb</depends> <depends>jboss.esb.quickstart.destination:service=Queue,name=transformpojoGw </depends> <depends>jboss.esb.quickstart.destination:service=Queue,name=transformpojoEsb </depends> <depends>jboss.esb.quickstart.destination:service=Queue,name=transformpojoResponse </depends> </jbossesb-deployment>
3.9 部署ESB
将整个工程导出成一个ESB文件,并保存至JBoss ESB Server的部署目录下,启动JBoss ESB Server即可。
4 ESB客户端
4.1 新建Java工程
这里略去操作过程以及添加所需要的Jar包,具体操作过程可参考第一个ESB实例说明。
4.2 发送消息的客户端
/***********************************************************************
* <p>Project Name: helloworldclient</p>
* <p>File Name: com.thu.afa.esb.jbossesb.client.TransformXML2POJOClient.java</p>
* <p>Copyright: Copyright (c) 2010</p>
* <p>Company: <a href="http://afa.thu.com">http://afa.thu.com</a></p>
***********************************************************************/
package com.thu.afa.esb.jbossesb.client;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.util.Properties;
import javax.jms.ObjectMessage;
import javax.jms.Queue;
import javax.jms.QueueConnection;
import javax.jms.QueueConnectionFactory;
import javax.jms.QueueSender;
import javax.jms.QueueSession;
import javax.naming.Context;
import javax.naming.InitialContext;
/**
* <p>Class Name: TransformXML2POJOClient</p>
* <p>Description: </p>
* @author Afa
* @date 2010-9-17
* @version 1.0
*/
public class TransformXML2POJOSendClient
{
private QueueConnection connection;
private QueueSession session;
private Queue queue;
public void setupConnection() throws Exception
{
Properties properties = new Properties();
properties.put(Context.INITIAL_CONTEXT_FACTORY, "org.jnp.interfaces.NamingContextFactory");
properties.put(Context.URL_PKG_PREFIXES, "org.jboss.naming:org.jnp.interfaces");
properties.put(Context.PROVIDER_URL, "jnp://127.0.0.1:1099");
InitialContext context = new InitialContext(properties);
QueueConnectionFactory factory = (QueueConnectionFactory) context.lookup("ConnectionFactory");
connection = factory.createQueueConnection();
queue = (Queue) context.lookup("queue/transformpojoGw");
session = connection.createQueueSession(false, QueueSession.AUTO_ACKNOWLEDGE);
connection.start();
System.out.println("Connection Started");
}
public void stop() throws Exception
{
if(connection != null) connection.stop();
if(session != null) session.close();
if(connection != null) connection.close();
}
public void sendAMessage(String text) throws Exception
{
QueueSender sender = session.createSender(queue);
ObjectMessage message = session.createObjectMessage(text);
sender.send(message);
sender.close();
}
public String readAsciiFile(String fileName) throws IOException
{
FileReader fr = null;
char[] thechars = null;
File thefile = new File(fileName);
fr = new FileReader( thefile );
int size = (int) thefile.length();
thechars = new char[size];
int count, index = 0;
while( ( count = fr.read( thechars, index, size ) ) > 0 )
{
size -= count;
index += count;
}
fr.close();
return new String(thechars);
}
/**
* <p>Title: </p>
* <p>Method Name: main</p>
* <p>Description: </p>
* @author: Afa
* @date: 2010-9-17
* @param args
*/
public static void main(String[] args) throws Exception
{
TransformXML2POJOSendClient client = new TransformXML2POJOSendClient();
client.setupConnection();
String fileContent = client.readAsciiFile("SampleOrder.xml");
System.out.println("---------------------------------------------");
System.out.println(fileContent);
System.out.println("---------------------------------------------");
client.sendAMessage(fileContent);
client.stop();
}
}
在客户端工程下创建SampleOrder.xml文件,并输入以下内容:
<Order orderId="1" orderDate="Wed Nov 15 13:45:28 EST 2006" statusCode="0" netAmount="59.97" totalAmount="64.92" tax="4.95"> <Customer userName="user1" firstName="Harry" lastName="Fletcher" state="SD"/> <OrderLines> <OrderLine position="1" quantity="1"> <Product productId="364" title="The 40-Year-Old Virgin " price="29.98"/> </OrderLine> <OrderLine position="2" quantity="1"> <Product productId="299" title="Pulp Fiction" price="29.99"/> </OrderLine> </OrderLines> </Order>
4.3 接收消息的客户端
/***********************************************************************
* <p>Project Name: helloworldclient</p>
* <p>File Name: com.thu.afa.esb.jbossesb.client.TransformXML2POJOReceiveClient.java</p>
* <p>Copyright: Copyright (c) 2010</p>
* <p>Company: <a href="http://afa.thu.com">http://afa.thu.com</a></p>
***********************************************************************/
package com.thu.afa.esb.jbossesb.client;
import java.util.Properties;
import javax.jms.Message;
import javax.jms.ObjectMessage;
import javax.jms.Queue;
import javax.jms.QueueConnection;
import javax.jms.QueueConnectionFactory;
import javax.jms.QueueReceiver;
import javax.jms.QueueSession;
import javax.jms.TextMessage;
import javax.naming.Context;
import javax.naming.InitialContext;
/**
* <p>Class Name: TransformXML2POJOReceiveClient</p>
* <p>Description: </p>
* @author Afa
* @date 2010-9-17
* @version 1.0
*/
public class TransformXML2POJOReceiveClient
{
private QueueConnection connection;
private QueueSession session;
private Queue queue;
public void setupConnection() throws Exception
{
Properties properties = new Properties();
properties.put(Context.INITIAL_CONTEXT_FACTORY, "org.jnp.interfaces.NamingContextFactory");
properties.put(Context.URL_PKG_PREFIXES, "org.jboss.naming:org.jnp.interfaces");
properties.put(Context.PROVIDER_URL, "jnp://127.0.0.1:1099");
InitialContext context = new InitialContext(properties);
QueueConnectionFactory factory = (QueueConnectionFactory) context.lookup("ConnectionFactory");
connection = factory.createQueueConnection();
queue = (Queue) context.lookup("queue/transformpojoResponse");
session = connection.createQueueSession(false, QueueSession.AUTO_ACKNOWLEDGE);
connection.start();
System.out.println("Connection Started");
}
public void stop() throws Exception
{
if(connection != null) connection.stop();
if(session != null) session.close();
if(connection != null) connection.close();
}
public void receiveMessage() throws Exception
{
QueueReceiver receiver = session.createReceiver(queue);
Message message = receiver.receive();
if(message != null)
{
if(message instanceof ObjectMessage)
{
ObjectMessage objectMessage = (ObjectMessage) message;
System.out.println(objectMessage.getObject().toString());
} else if (message instanceof TextMessage) {
TextMessage textMessage = (TextMessage) message;
System.out.println(textMessage.getText());
}
}
receiver.close();
}
public static void main(String[] args) throws Exception
{
TransformXML2POJOReceiveClient client = new TransformXML2POJOReceiveClient();
client.setupConnection();
client.receiveMessage();
client.stop();
}
}
4.4 运行客户端
首先运行接收消息的客户端,然后运行发送消息的客户端,即可得到如下输出结果,以下三图从上到下依次是:发送消息客户端输出结果,接收消息客户端输出结果,ESB服务器控制台输出结果。
-----------------------------------------------------
Stay Hungry, Stay Foolish!
http://yarafa.iteye.com
Afa
Apr 12nd, 2011
-----------------------------------------------------