Over a million developers have joined DZone.
{{announcement.body}}
{{announcement.title}}

Microservices With Camel and WildFly Swarm - Introduction

DZone's Guide to

Microservices With Camel and WildFly Swarm - Introduction

Camel can make your enterprise integrations extensible and easier to maintain.

Free Resource

Share, secure, distribute, control, and monetize your APIs with the platform built with performance, time-to-value, and growth in mind. Free 90 day trial 3Scale by Red Hat

This is the first in a series of articles that explore the use of Camel with WildFly Swarm to create enterprise Microservices.

If you are an enterprise Java developer, there is a very good chance that a lot of the work you do involves reading, transforming and saving data across multiple different kinds of platforms. Files, SQL, NoSQL, email, FTP, HTTP, JMX, JMS... These are just a few of the platforms and interfaces that you’ll be expected to interact with on a daily basis.

Java has excellent libraries supporting all these platforms, but you’ll quickly find that the libraries have little in common. Take a look at this sample code for sending a JMS message:

         /*
         * Create a JNDI API InitialContext object if none exists
         * yet.
         */
        Context jndiContext = null;
       try {
            jndiContext = new InitialContext();
        } catch (NamingException e) {
            System.out.println("Could not create JNDI API context: " +
                e.toString());
            System.exit(1);
        }

       /*
         * Look up connection factory and destination.  If either
         * does not exist, exit.  If you look up a
         * TopicConnectionFactory or a QueueConnectionFactory,
         * program behavior is the same.
         */
        ConnectionFactory connectionFactory = null;
        Destination dest = null;

       try {
            connectionFactory = (ConnectionFactory) jndiContext.lookup(
                    "jms/ConnectionFactory");
            dest = (Destination) jndiContext.lookup(destName);
        } catch (Exception e) {
            System.out.println("JNDI API lookup failed: " + e.toString());
            e.printStackTrace();
            System.exit(1);
        }

       /*
         * Create connection.
         * Create session from connection; false means session is
         * not transacted.
         * Create producer and text message.
         * Send messages, varying text slightly.
         * Send end-of-messages message.
         * Finally, close connection.
         */
        Connection connection = null;
        MessageProducer producer = null;

       try {
            connection = connectionFactory.createConnection();

           Session session =
                connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
            producer = session.createProducer(dest);

           TextMessage message = session.createTextMessage();

           for (int i = 0; i < NUM_MSGS; i++) {
                message.setText("This is message " + (i + 1));
                System.out.println("Sending message: " + message.getText());
                producer.send(message);
            }

           /*
             * Send a non-text control message indicating end of
             * messages.
             */
            producer.send(session.createMessage());
        } catch (JMSException e) {
            System.out.println("Exception occurred: " + e.toString());
        } finally {
            if (connection != null) {
                try {
                    connection.close();
                } catch (JMSException e) {
                }
            }
        }

Compare this to the simple task of saving content to a file:

BufferedWriter writer = null;
try
{
    writer = new BufferedWriter( new FileWriter( yourFileName));
    writer.write( yourString);

}
catch ( IOException e)
{
}
finally
{
    try
    {
        if ( writer != null)
        writer.close( );
    }
    catch ( IOException e)
    {
    }
}

At a high level, the outcome of these two operations is much the same: take some data and send it somewhere else. At a low level, there is almost no similarity between these two operations. Both use different classes that are initialized in different ways and expose different methods.

Designing code that can elegantly transfer data between these services is not as easy as you might expect. It is tempting to solve this problem with a pair of interfaces like this:

public interface DataProducer {
String produce();
}

public interface DataConsumer {
void consume(final String data);
}

This simplified view of producing and consuming data is only half the battle. Now you need to actually implement them for all of various services that you interact with. Once you have done that, you need to deal with the additional metadata that these services expose e.g. files have modified dates, JMS and HTTP services use headers, email has recipients.

As these edge cases start to add up it should become clear just how monumental the task of interacting with this set of enterprise services is if you want to do it in a extensible and maintainable way.

This is where Camel comes in. Camel provides dozens of components which can be used to route information using the patterns described in the book Enterprise Integration Patterns. By taking advantage of Camel you take advantage of nearly a decade's worth of development exposing enterprise systems in a extensible and maintainable way.

Now that you have an idea of why you would want to use Camel, we’ll move onto integrating it with WildFly Swarm.

You can find articles in this series here.

Discover how you can achielve enterpriese agility with microservices and API management

Topics:
java ,wildfly ,wildfly swarm ,camel

Published at DZone with permission of Matthew Casperson, DZone MVB. See the original article here.

Opinions expressed by DZone contributors are their own.

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}