Monday 30 July 2012

Soap Web Service with attachment Over JMS

  • dependency
  • 
        com.sun.messaging.mq
        imqxm
        4.6-b01
    
    
        javaee
        javaee-api
        5
    
    
        xalan
        xalan
        2.7.0
    
    
        com.sun.messaging.mq
        jaxm-api
        4.6-b01
                
    
  • JMS message sender (Embedded SoapMessage with Attachment)
  • import com.google.common.io.Files;
    import com.sun.messaging.xml.MessageTransformer;
    
    import javax.activation.DataHandler;
    import javax.activation.FileDataSource;
    import javax.jms.*;
    import javax.naming.Context;
    import javax.naming.InitialContext;
    import javax.xml.soap.*;
    import java.io.File;
    import java.io.IOException;
    import java.nio.charset.Charset;
    import java.util.Hashtable;
    
    public class MockWebServiceOverJMSSender {
        private static final String CONNECTION_FACTORY_JNDI_NAME = "weblogic.jms.XAConnectionFactory";
        private static final String QUEUE_JNDI_NAME = "jms/TestQueueJNDI";
    
        public static void sendMessage() {
            try {
                QueueConnection connection = null;
                QueueSession session = null;
                QueueSender queueSender = null;
                try {
                    Hashtable<String,String> properties = new Hashtable();
                    properties.put(Context.INITIAL_CONTEXT_FACTORY, "weblogic.jndi.WLInitialContextFactory");
                    properties.put(Context.PROVIDER_URL, "t3://localhost:7001");
    
                    InitialContext context = new InitialContext(properties);
                    QueueConnectionFactory connectionFactory = (QueueConnectionFactory) context.lookup(CONNECTION_FACTORY_JNDI_NAME);
                    connection = connectionFactory.createQueueConnection();
                    session = connection.createQueueSession(false, 0);
                    Queue queue = (Queue) context.lookup(QUEUE_JNDI_NAME);
                    queueSender = session.createSender(queue);
    
                    MessageFactory messageFactory = MessageFactory.newInstance();
                    SOAPMessage soapMessage = messageFactory.createMessage();
                    soapMessage.setProperty(SOAPMessage.WRITE_XML_DECLARATION, "true");
                    SOAPPart soapPart = soapMessage.getSOAPPart();
                    SOAPEnvelope envelope = soapPart.getEnvelope();
                    SOAPBody soapBody = envelope.getBody();
    
                    soapBody.setTextContent(buildSoapBodyContent());
    
                    AttachmentPart attachment = buildSoapAttachment(soapMessage);
                    soapMessage.addAttachmentPart(attachment);
    
                    soapMessage.saveChanges();
                    Message message = MessageTransformer.SOAPMessageIntoJMSMessage(soapMessage, session);
                    queueSender.send(message);
                } finally {
                    queueSender.close();
                    session.close();
                    connection.close();
                }
            } catch (Exception e) {
                e.printStackTrace();
                System.exit(0);
            }
        }
    
        private static String buildSoapBodyContent() throws IOException {
            String responseFile = "c:/temp/PoliceAVOApplicationResponse-Non-provisional.xml";
            return Files.toString(new File(responseFile), Charset.forName("UTF-8"));
        }
    
        private static AttachmentPart buildSoapAttachment(SOAPMessage soapMessage) {
            DataHandler dh = new DataHandler(new FileDataSource("c:/temp/test_avo.pdf"));
            return soapMessage.createAttachmentPart(dh);
        }
    
        public static void main(String args[]) {
            sendMessage();
        }
    
  • JMS consumer(parse message body & save attachment to disk)
  • import au.gov.nsw.police.nodi.common.IOHelper;
    import com.google.common.io.Files;
    import com.sun.messaging.xml.MessageTransformer;
    import org.w3c.dom.Document;
    import org.xml.sax.SAXException;
    
    import javax.jms.*;
    import javax.naming.Context;
    import javax.naming.InitialContext;
    import javax.xml.parsers.DocumentBuilder;
    import javax.xml.parsers.DocumentBuilderFactory;
    import javax.xml.parsers.ParserConfigurationException;
    import javax.xml.soap.*;
    import javax.xml.xpath.*;
    import java.io.ByteArrayInputStream;
    import java.io.File;
    import java.io.IOException;
    import java.io.InputStream;
    import java.util.Date;
    import java.util.Hashtable;
    import java.util.Iterator;
    
    public class MockJMSMessageConsumer {
        private static final String CONNECTION_FACTORY_JNDI_NAME = "weblogic.jms.XAConnectionFactory";
        private static final String QUEUE_JNDI_NAME = "jms/TestQueueJNDI";
    
        private static void consumeMessage() {
            try {
                QueueConnection connection = null;
                QueueSession session = null;
                QueueReceiver queueReceiver = null;
                try {
                    Hashtable<String, String> properties = new Hashtable();
                    properties.put(Context.INITIAL_CONTEXT_FACTORY, "weblogic.jndi.WLInitialContextFactory");
                    properties.put(Context.PROVIDER_URL, "t3://localhost:7001");
    
                    InitialContext context = new InitialContext(properties);
                    QueueConnectionFactory connectionFactory = (QueueConnectionFactory) context.lookup(CONNECTION_FACTORY_JNDI_NAME);
                    connection = connectionFactory.createQueueConnection();
                    session = connection.createQueueSession(false, 0);
                    Queue queue = (Queue) context.lookup(QUEUE_JNDI_NAME);
                    queueReceiver = session.createReceiver(queue);
                    connection.start();
    
                    while (true) {
                        Message message = queueReceiver.receive(1);
                        MessageFactory messageFactory = MessageFactory.newInstance();
    
                        if (message != null) {
                            SOAPMessage soapMessage = MessageTransformer.SOAPMessageFromJMSMessage(message, messageFactory);
                            onMessage(soapMessage);
                        }
                    }
                } finally {
                    queueReceiver.close();
                    session.close();
                    connection.close();
                }
            } catch (Exception e) {
                e.printStackTrace(System.err);
                System.exit(0);
            }
        }
    
        private static void onMessage(SOAPMessage soapMessage) {
            try {
                System.out.println("Start to processing message from ESB...");
                SOAPBody soapBody = soapMessage.getSOAPPart().getEnvelope().getBody();
    
                Iterator iterator = soapMessage.getAttachments();
                if (iterator.hasNext()) {
                    AttachmentPart attachmentPart = (AttachmentPart) iterator.next();
                    System.out.println("here");
                    parseMetadataFromSoapMessage(soapBody, attachmentPart);
                }
                System.out.println("Finish to processing message from ESB");
            } catch (Throwable e) {
                e.printStackTrace();
            }
        }
    
    
        private static void parseMetadataFromSoapMessage(SOAPBody soapBody, AttachmentPart attachmentPart) throws IOException, SAXException, ParserConfigurationException, XPathExpressionException, SOAPException {
            String content = soapBody.getTextContent();
            Document doc = buildDocumentFromString(content);
    
            XPath xPath = createXPath();
            String courtReferenceNumber = getStringValueWithGiveXPath(xPath, doc, "/n1:PublishDocumentMessage/@ProceedingNumber");
            String courtName = getStringValueWithGiveXPath(xPath, doc, "/n1:PublishDocumentMessage/n1:Listing/Court/@Name");
            String eventNumber = getStringValueWithGiveXPath(xPath, doc, "/n1:PublishDocumentMessage/n1:QuestionsAndAnswers/n1:DataField[@Name='IDF POLAPPEVENTNO']/@Value");
            String cni = getStringValueWithGiveXPath(xPath, doc, "/n1:PublishDocumentMessage/n1:Participant[n1:ParticipantID[@ParticipantRole='DEFENDANT']]/n1:CrimeIndividual/common:IndividualDetails/@CNI");
            System.out.println("court reference number: " + courtReferenceNumber);
            System.out.println("court name: " + courtName);
            System.out.println("event number: " + eventNumber);
            System.out.println("cni: " + cni);
    
            saveAttachmentToDisk(attachmentPart);
        }
    
        private static Document buildDocumentFromString(String content) throws ParserConfigurationException, SAXException, IOException {
            DocumentBuilderFactory docBuilderFactory = DocumentBuilderFactory.newInstance();
            docBuilderFactory.setNamespaceAware(true);
            DocumentBuilder docBuilder = docBuilderFactory.newDocumentBuilder();
            InputStream inputStream = new ByteArrayInputStream(content.getBytes());
            return docBuilder.parse(inputStream);
        }
    
        private static XPath createXPath() {
            XPathFactory xPathfactory = XPathFactory.newInstance();
            XPath xpath = xPathfactory.newXPath();
            xpath.setNamespaceContext(new AVONamespaceContext());
    
            return xpath;
        }
    
        private static String getStringValueWithGiveXPath(XPath xpath, Document document, String expression) throws XPathExpressionException {
            XPathExpression xPathExpression = xpath.compile(expression);
            return (String) xPathExpression.evaluate(document, XPathConstants.STRING);
        }
    
        private static void saveAttachmentToDisk(AttachmentPart attachmentPart) throws IOException, SOAPException {
            byte[] pdfFile= IOHelper.readInputStream(attachmentPart.getDataHandler().getInputStream());
            Date now = new Date();
            Files.write(faxImages, new File("c:/temp/" + now.getTime() + ".pdf"));
        }
    
        public static void main(String args[]) {
            consumeMessage();
        }
    
  • help class
  • import javax.xml.XMLConstants;
    import javax.xml.namespace.NamespaceContext;
    import java.util.Iterator;
    
    public class AVONamespaceContext implements NamespaceContext {
        public String getNamespaceURI(String prefix) {
            if (prefix == null) throw new NullPointerException("Invalid Namespace Prefix");
            else if (prefix.equals(XMLConstants.DEFAULT_NS_PREFIX)) {
                return "http://www.w3.org/2001/XMLSchema-instance";
            } else if ("n1".equals(prefix)) {
                return "http://cats.agd.nsw.gov.au/PublishDocumentMessage/v1_0";
            } else if ("common".equals(prefix)) {
                return "http://cats.agd.nsw.gov.au/DocumentLodgementInterfaces/Common/v1_0";
            } else if ("cim".equals(prefix)) {
                return "http://cim.justicesector.nsw.gov.au/Common/1";
            } else if ("as4590".equals(prefix)) {
                return "http://cim.justicesector.nsw.gov.au/as459";
            } else {
                return XMLConstants.NULL_NS_URI;
            }
        }
    
        public String getPrefix(String namespaceURI) {
            return null;
        }
    
        public Iterator getPrefixes(String namespaceURI) {
            return null;
        }
    }
    
  • Another Solution
  • You don't need to dependent the above dependencies. You just implement your own transformer. My sample as follow:
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    
    import javax.jms.BytesMessage;
    import javax.jms.JMSException;
    import javax.jms.Message;
    import javax.jms.Session;
    import javax.xml.messaging.JAXMException;
    import javax.xml.soap.*;
    import java.io.*;
    import java.util.Enumeration;
    import java.util.Hashtable;
    import java.util.Iterator;
    
    import static com.google.common.base.Throwables.getStackTraceAsString;
    
    /**
     * The Rcode>Transformer</code> class encapsulates the functionality
     * to transform SOAP and JMS messages.
     */
    public class MessageTransformer {
        private static final Logger log = LoggerFactory.getLogger(MessageTransformer.class);
        private MessageTransformer() {
        }
    
        /**
         * Transforms a <code>javax.xml.soap.SOAPMessage</code> message
         * into a <code>javax.jms.Message</code> message.
         *
         * @param soapMessage the SOAPMessage to be converted to the JMS Message.
         * @param session     The JMS Session to be used to construct the JMS Message.
         * @throws JAXMException If any error is encountered when transforming the message.
         */
        public static Message SOAPMessageIntoJMSMessage(SOAPMessage soapMessage, Session session) throws JAXMException {
            try {
                /**
                 * Construct a bytes message object.
                 * This is to make sure the utility works across all vendors.
                 */
                BytesMessage bytesMessage = session.createBytesMessage();
    
                /**
                 * This is here to make sure that RI's bad SOAP implementation
                 * will get updated for internal buffers.
                 */
                soapMessage.saveChanges();
    
                writeMimeHeaders(soapMessage, bytesMessage);
                writeSOAPBody(soapMessage, bytesMessage);
    
                return bytesMessage;
            } catch (JAXMException JAXMe) {
                throw JAXMe;
            } catch (Exception e) {
                log.error(getStackTraceAsString(e));
                throw new JAXMException(e);
            }
        }
    
        private static void writeMimeHeaders(SOAPMessage soapMessage, BytesMessage bytesMessage) throws Exception {
            MimeHeaders mimeHeaders = soapMessage.getMimeHeaders();
            Hashtable hashtable = convertMimeHeadersToHashtable(mimeHeaders);
    
            ByteArrayOutputStream mimeOut = writeHashtableToByteArrayOutputStream(hashtable);
    
            byte[] mimeHeadersBytes = mimeOut.toByteArray();
            int mimeHeadersLength = mimeHeadersBytes.length;
            bytesMessage.writeInt(mimeHeadersLength);
            bytesMessage.writeBytes(mimeHeadersBytes);
            mimeOut.close();
            log.debug("SOAP to JMS mime headers length: {}", mimeHeadersLength);
        }
    
        /**
         * Convert MimeHeaders to Hashtable.  The hashtable is then used to write
         * to JMS BytesMessage.
         */
        private static Hashtable convertMimeHeadersToHashtable(MimeHeaders mimeHeaders) {
            Hashtable hashtable = new Hashtable();
            Iterator it = mimeHeaders.getAllHeaders();
            while (it.hasNext()) {
                MimeHeader mimeHeader = (MimeHeader) it.next();
                hashtable.put(mimeHeader.getName(), mimeHeader.getValue());
            }
    
            return hashtable;
        }
    
        private static ByteArrayOutputStream writeHashtableToByteArrayOutputStream(Hashtable hashtable) throws IOException {
            ByteArrayOutputStream mimeOut = new ByteArrayOutputStream();
            ObjectOutputStream objectOutputStream = new ObjectOutputStream(mimeOut);
            objectOutputStream.writeObject(hashtable);
            objectOutputStream.flush();
            objectOutputStream.close();
            return mimeOut;
        }
    
        private static void writeSOAPBody(SOAPMessage soapMessage, BytesMessage bytesMessage) throws Exception {
            ByteArrayOutputStream bodyOutput = new ByteArrayOutputStream();
            soapMessage.writeTo(bodyOutput);
    
            byte[] bodyBytes = bodyOutput.toByteArray();
            int bodyLength = bodyBytes.length;
            bytesMessage.writeInt(bodyLength);
            bytesMessage.writeBytes(bodyBytes);
    
            bodyOutput.close();
            log.debug("SOAP to JMS body length: {}", bodyLength);
        }
    
    
        /**
         * Extracts a <code>javax.xml.soap.SOAPMessage</code> object from the
         * <code>javax.jms.Message</code> object into which it was transformed
         * using the <code>SOAPMessageIntoJMSMessage</code> method.
         * <p/>* The <code>MessageFactory</code> parameter is used to construct the
         * <code>javax.xml.soap.SOAPMessage</code> object.
         * <p/>* If <code>MessageFactory</code> is <code>null</code> then the
         * default SOAP MessageFactory will be used to construct the
         * SOAP message.
         *
         * @param message        The JMS message from which the SOAP message is to be extracted.
         * @param messageFactory The SOAP MessageFactory to be used to contruct the SOAP message.
         * @throws JAXMException If any error is encountered when extracting the message.
         */
        public static SOAPMessage extractSOAPMessageFromJMSMessage(Message message, MessageFactory messageFactory) throws JAXMException {
            BytesMessage bytesMessage = (BytesMessage) message;
            try {
                MimeHeaders mimeHeaders = readMimeHeaders(bytesMessage);
                ByteArrayInputStream bodyByteArrayInputStream = readSoapBodyToByteArrayInputStream(bytesMessage);
    
                return constructSoapMessage(messageFactory, mimeHeaders, bodyByteArrayInputStream);
            } catch (Exception e) {
                throw new JAXMException(e);
            }
        }
    
        private static MimeHeaders readMimeHeaders(BytesMessage bytesMessage) throws JMSException, IOException, ClassNotFoundException {
            int mimeHeadersLength = bytesMessage.readInt();
            byte[] mimeHeadersBytes = new byte[mimeHeadersLength];
            bytesMessage.readBytes(mimeHeadersBytes, mimeHeadersLength);
    
            ByteArrayInputStream mimeHeadersByteArrayInputStream = new ByteArrayInputStream(mimeHeadersBytes);
            ObjectInputStream objectInputStream = new ObjectInputStream(mimeHeadersByteArrayInputStream);
            Hashtable hashtable = (Hashtable) objectInputStream.readObject();
            return convertHashtableToMimeHeaders(hashtable);
        }
    
        private static MimeHeaders convertHashtableToMimeHeaders(Hashtable hashtable) {
            MimeHeaders mimeHeaders = new MimeHeaders();
    
            Enumeration enm = hashtable.keys();
            while (enm.hasMoreElements()) {
                Object key = enm.nextElement();
                mimeHeaders.addHeader((String) key, (String) hashtable.get(key));
                log.debug("mime-header: {} = {}", key, hashtable.get(key));
            }
    
            return mimeHeaders;
        }
    
        private static ByteArrayInputStream readSoapBodyToByteArrayInputStream(BytesMessage bytesMessage) throws JMSException {
            int bodyLength = bytesMessage.readInt();
            byte[] buf = new byte[bodyLength];
            bytesMessage.readBytes(buf, bodyLength);
    
            return new ByteArrayInputStream(buf);
        }
    
        private static SOAPMessage constructSoapMessage(MessageFactory messageFactory, MimeHeaders mimeHeaders,
                                                        ByteArrayInputStream bodyByteArrayInputStream) throws SOAPException, IOException {
            if (messageFactory == null) {
                messageFactory = getMessageFactory();
            }
    
            return messageFactory.createMessage(mimeHeaders, bodyByteArrayInputStream);
        }
    
        private static MessageFactory getMessageFactory() throws SOAPException {
            return MessageFactory.newInstance();
        }
    }
    
  • reference
  • SOAP over Java Message Service 1.0

Create xml Document from File or String & convert Document to String

  • Create xml Document from File or String
  • public Document buildDocumentFromExternalResource() throw Exception {
        String content = "....";
        DocumentBuilderFactory docBuilderFactory = DocumentBuilderFactory.newInstance();
        docBuilderFactory.setNamespaceAware(true);
        DocumentBuilder docBuilder = docBuilderFactory.newDocumentBuilder();
        InputStream inputStream = new ByteArrayInputStream(content.getBytes());
        Document doc = docBuilder.parse(inputStream);
        // read from file
        doc = docBuilder.parse(new File("c:/temp/myContent.xml"));
    }
    
  • convert Document to String
  • public String convertDocumentToString(SOAPBody soapBody) throw Excepiton {
            Document doc = soapBody.getOwnerDocument();
            Source source = new DOMSource(doc);
            StringWriter out = new StringWriter();
            Result result = new StreamResult(out);
    
            TransformerFactory transformerFactory = TransformerFactory.newInstance();
            Transformer transformer = transformerFactory.newTransformer();
            transformer.transform(source, result);
    
            String content = out.toString();
       }
    

Wednesday 25 July 2012

A simple JMSClient to test JMS queue/topic in Weblogic

import javax.jms.*;
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import java.util.Hashtable;

public class TestJMS {
    private static InitialContext context = null;
    private static QueueConnectionFactory connectionFactory = null;
    private static QueueConnection connection = null;
    private static QueueSession session = null;
    private static Queue queue = null;
    private static QueueSender queueSender = null;
    private static TextMessage message = null;
    //Using the Default Connection Factories
    //ref --> http://docs.oracle.com/cd/E15051_01/wls/docs103/jms/fund.html
    private static final String CONNECTION_FACTORY_JNDI_NAME = "weblogic.jms.ConnectionFactory";
    private static final String QUEUE_JNDI_NAME = "Police.Eno.CourtServiceQueue";

    public TestJMS() {
        super();
    }

    public static void sendMessage(String messageText) {
        try {
            try {
                Hashtable properties = new Hashtable();
                properties.put(Context.INITIAL_CONTEXT_FACTORY, "weblogic.jndi.WLInitialContextFactory");
                properties.put(Context.PROVIDER_URL, "t3://localhost:7001");

                context = new InitialContext(properties);
                connectionFactory = (QueueConnectionFactory) context.lookup(CONNECTION_FACTORY_JNDI_NAME);
                connection = connectionFactory.createQueueConnection();
                session = connection.createQueueSession(false, 0);

                queue = (Queue) context.lookup(QUEUE_JNDI_NAME);
                queueSender = session.createSender(queue);
                message = session.createTextMessage();
                message.setText(messageText);
                queueSender.send(message);
            } finally {
                message = null;
                queueSender.close();
                queueSender = null;
                queue = null;
                session.close();
                session = null;
                connection.close();
                connection = null;
                connectionFactory = null;
                context = null;
            }
        } catch (NamingException e) {
            e.printStackTrace(System.err);
            System.exit(0);
        } catch (JMSException e) {
            e.printStackTrace(System.err);
            System.exit(0);
        }
    }

    public static void main(String args[]) {
        sendMessage("test message here!!!");
    }
}

Monday 9 July 2012

Regular express validate date time

reference:
http://stackoverflow.com/questions/1315376/regular-expression-for-date-time-format-mm-dd-yy-hhmmss-am-pm-in-asp-net-reg


RegEx for matching all dates, including leap years.
  1. For DD-MM-YYYY format
  2. ^(?:31#(?:(?:0[13578])|(?:1[02]))#)|(?:(?:29|30)#(?:(?:0[1,3-9])|(?:1[0-2]))#)(?:(?:1[6-9]|[2-9]\d)\d{2})$|^(?:29#02#(?:(?:(?:1[6-9]|[2-9]\d)(?:0[48]|[2468][048]|[13579][26])|(?:(?:16|[2468][048]|[3579][26])00))))$|^(?:(?:0[1-9])|(?:1\d)|(?:2[0-8]))#(?:(?:0[1-9])|(?:1[0-2]))#(?:(?:1[6-9]|[2-9]\d)\d{2})$
    
  3. For MM-DD-YYYY format
  4. ^(?:(?:(?:0?[13578]|1[02])#31)\1|(?:(?:0?[1,3-9]|1[0-2])#(?:29|30)\2))(?:(?:1[6-9]|[2-9]\d)?\d{2})$|^(?:0?2#29\3(?:(?:(?:1[6-9]|[2-9]\d)?(?:0[48]|[2468][048]|[13579][26])|(?:(?:16|[2468][048]|[3579][26])00))))$|^(?:(?:0?[1-9])|(?:1[0-2]))#(?:0?[1-9]|1\d|2[0-8])\4(?:(?:1[6-9]|[2-9]\d)?\d{2})$
    
  5. Java Code
  6. String inputDate;
    String regex="^(?:31/(?:(?:0[13578])|(?:1[02]))/)|(?:(?:29|30)/(?:(?:0[1,3-9])|(?:1[0-2]))/)(?:(?:1[6-9]|[2-9]\\d)\\d{2})$|^(?:29/02/(?:(?:(?:1[6-9]|[2-9]\\d)(?:0[48]|[2468][048]|[13579][26])|(?:(?:16|[2468][048]|[3579][26])00))))$|^(?:(?:0[1-9])|(?:1\\d)|(?:2[0-8]))/(?:(?:0[1-9])|(?:1[0-2]))/(?:(?:1[6-9]|[2-9]\\d)\\d{2})$";
    Pattern pattern = Pattern.compile(inputDate);
    Matcher matcher = pattern.matcher(inputDate);
    boolean found = matcher.matches();
    
  7. For Time
  8. ^([0|1][0-9]|2[0-3]):[0-5][0-9]:[0-5][0-9]$