460 likes | 477 Views
Enterprise Messaging and Data Access Advanced Web Applications Development Technion CS 236606 Spring 2003, Class 3. Gidon Gershinsky. Overview. JMS, JNDI, JDBC Enterprise Messaging Traditional network communication Messaging paradigm Message-Oriented Middleware Publish/Subscribe messaging
E N D
Enterprise Messaging and Data AccessAdvanced Web Applications DevelopmentTechnion CS 236606 Spring 2003, Class 3 Gidon Gershinsky
Overview • JMS, JNDI, JDBC • Enterprise Messaging • Traditional network communication • Messaging paradigmMessage-Oriented Middleware • Publish/Subscribe messaging • Point-to-Point messaging • Architecture • Centralized • Multicast • Hybrid • Samples, JNDI (java naming & directory interface) • Assured delivery • Durable subscription • Persistent publishing • Acknowledged delivery
Overview (cont) • Enterprise Application Integration (EAI) • JDBC
Traditional networking • Datagram protocols: IP, UDP • Streaming protocols: TCP • RPC: RMI, CORBA • Synchronous • Tightly coupled(full knowledge, inc address, protocol, etc,of the communication peer(s))
Messaging • “e-mail for applications” • Asynchronous communication:The sender and receiver do not have to be available at the same time in order to communicate. • Loosely coupled:The sender does not need to know anything about the receiver, nor does the receiver need to know anything about the sender; they only need to know what message format and what destination to use. • Utilizes the TCP, UDP unicast/multicast, HTTP, etc.
Messaging • Message: “a package of business data that is sent from one application to another over the network. Self-describing – contains all the necessary context to allow the recipients to carry out their work independently” • Different from a “datagram”: • Few bytes to few megabytes (UDP: up to 64K) • More structured (headers, properties, body types) • Different from a “stream” • Different from file delivery
Message-Oriented Middleware (MOM) • Asynchronous,loosely coupled messaging • Fault tolerance • Load balancing • Scalability • Transactional support • JMS Terminology:“Vendor”, “Provider”, “Client”, “Destination”,“Producer”, “Consumer”
What is JMS • Java Message Service:A Java API that allows applications to create, send, receive, and read messages • Interface specification only • Vendor-agnosticApplication developers reuse the same API to access different MOM vendors.IBM MQSeries, Tibco, SpiritSoft, Fiorano, SoftwiredMicrosoft MSMQ • No vendor interoperability:API is the same, but two implementations wont talk to each other. • Implementation switch: Little or no change in application code is requiredNo “standard compliance” body
JMS Domains • Publish/Subscribe“One-to-many” or “Many-to-many”Many consumers per message • Point-to-PointOne consumer per message
Publish/Subscribe Messaging • Topic – “destination” (virtual data channel) • Producer is a “publisher”Consumer is a “subscriber” • Publishers and subscribers are generally anonymous • Default” “Push” mode
Publish/Subscribe Messaging • Topics retain messages only as long as it takes to distribute them to current subscribers. There is a timing dependency between publishers and subscribers, because a client that subscribes to a topic can consume only messages published after the client has created a subscription, and the subscriber must continue to be active in order for it to consume messages. • The JMS API relaxes this timing dependency to some extent by allowing clients to create durable subscriptions. • Use pub/sub messaging when each message can be processed by zero, one, or many consumers.
Point-to-Point Messaging • Queue: virtual data channel (“destination”) • Producer is a “sender”Consumer is a “receiver” • “Pull” mode
Point-to-Point Messaging • Each message is addressed to a specific queue, and receiving clients extract messages from the queue(s) established to hold their messages. Queues retain all messages sent to them until the messages are consumed or until the messages expire. • Each message has only one consumer. • There are no timing dependencies between a sender and a receiver of a message. The receiver can fetch the message whether or not it is running when the client sends the message. • The receiver acknowledges the successful processing of a message. • Use PTP messaging when every message you send must be processed successfully by one consumer.
Architecture type: Centralized • Message “server”, “router” or “broker” • Decouples clients: see only the server, not other clients. Allows to add/remove clients without impacting the system. • “Hub-and-spoke” topology • “Message server” may be a cluster of distributed servers operating as a single logical unit.
Architecture type: Multicast • No central server • Based on “IP multicast” • Network layer handles routing automatically • Server-like functionality at each client
Architecture type: Hybrid • Both TCP/IP and IP multicast in use
JMS example: P2P Sender (1/3) • import javax.jms.*; import javax.naming.*; public class SimpleQueueSender { public static void main(String[] args) { String queueName = null; Context jndiContext = null; QueueConnectionFactory queueConnectionFactory = null; QueueConnection queueConnection = null; QueueSession queueSession = null; Queue queue = null; QueueSender queueSender = null; TextMessage message = null; final int NUM_MSGS; final String MSG_TEXT = new String("Here is a message"); Properties env = new Properties(); // Specify the vendor-specific JDNI properties
JMS example: P2P Sender (2/3) • queueName = “Test Queue”;/* * Create a JNDI InitialContext object */ try { jndiContext = new InitialContext(env); } catch (NamingException e) { System.out.println("Could not create JNDI " + "context: " + e.toString()); System.exit(1); } /* * Look up connection factory and queue. If either does * not exist, exit. */ try { queueConnectionFactory = (QueueConnectionFactory) jndiContext.lookup("QueueConnectionFactory"); queue = (Queue) jndiContext.lookup(queueName); } catch (NamingException e) { System.out.println("JNDI lookup failed: " + e.toString()); System.exit(1); }
JMS example: P2P Sender (3/3) • try { queueConnection = queueConnectionFactory.createQueueConnection(); queueSession = queueConnection.createQueueSession(false, Session.AUTO_ACKNOWLEDGE); queueSender = queueSession.createSender(queue); message = queueSession.createTextMessage(); for (int i = 0; i < NUM_MSGS; i++) { message.setText(MSG_TEXT + " " + (i + 1)); System.out.println("Sending message: " + message.getText()); queueSender.send(message); }} catch (JMSException e) { System.out.println("Exception occurred: " + e.toString()); }
JMS example: P2P Receiver (1/3) • import javax.jms.*; import javax.naming.*; public class SimpleQueueReceiver { public static void main(String[] args) { String queueName = null; Context jndiContext = null; QueueConnectionFactory queueConnectionFactory = null; QueueConnection queueConnection = null; QueueSession queueSession = null; Queue queue = null; QueueReceiver queueReceiver = null; TextMessage message = null; Properties env = new Properties(); // Specify the vendor-specific JDNI properties
JMS example: P2P Receiver (2/3) • queueName = “Test Queue”;/* * Create a JNDI InitialContext object if none exists yet. */ try { jndiContext = new InitialContext(env); } catch (NamingException e) { System.out.println("Could not create JNDI " + "context: " + e.toString()); System.exit(1); } /* * Look up connection factory and queue. If either does * not exist, exit. */ try { queueConnectionFactory = (QueueConnectionFactory) jndiContext.lookup("QueueConnectionFactory"); queue = (Queue) jndiContext.lookup(queueName); } catch (NamingException e) { System.out.println("JNDI lookup failed: " + e.toString()); System.exit(1); }
JMS example: P2P Receiver (3/3) • try { queueConnection = queueConnectionFactory.createQueueConnection(); queueSession = queueConnection.createQueueSession(false, Session.AUTO_ACKNOWLEDGE); queueReceiver = queueSession.createReceiver(queue); queueConnection.start(); while (true) { Message m = queueReceiver.receive(1); if (m != null) { if (m instanceof TextMessage) { message = (TextMessage) m; System.out.println("Reading message: " + message.getText());}} catch (JMSException e) { System.out.println("Exception occurred: " + e.toString()); }
JMS example: Pub/Sub Publisher (1/3) • import javax.jms.*; import javax.naming.*; public class SimpleTopicPublisher{ public static void main(String[] args) { String topicName = null; Context jndiContext = null; TopicConnectionFactory topicConnectionFactory = null; TopicConnection topicConnection = null; TopicSession topicSession = null; Topic topic = null; TopicPublisher topicPublisher = null; TextMessage message = null; final int NUM_MSGS; final String MSG_TEXT = new String("Here is a message"); Properties env = new Properties(); // Specify the vendor-specific JDNI properties
JMS example: Pub/Sub Publisher (2/3) • topicName = “Test Topic”;/* * Create a JNDI InitialContext */ try { jndiContext = new InitialContext(env); } catch (NamingException e) { System.out.println("Could not create JNDI " + "context: " + e.toString()); System.exit(1); } /* * Look up connection factory and topic. If either does * not exist, exit. */try { topicConnectionFactory = (TopicConnectionFactory) jndiContext.lookup("TopicConnectionFactory"); topic = (Topic) jndiContext.lookup(topicName); } catch (NamingException e) { System.out.println("JNDI lookup failed: " + e.toString()); System.exit(1); }
JMS example: Pub/Sub Publisher (3/3) • try { topicConnection = topicConnectionFactory.createTopicConnection(user, psswd); topicSession = topicConnection.createTopicSession(false, Session.AUTO_ACKNOWLEDGE); topicPublisher = topicSession.createPublisher(topic); message = topicSession.createTextMessage(); for (int i = 0; i < NUM_MSGS; i++) { message.setText(MSG_TEXT + " " + (i + 1)); System.out.println("Publishing message: " + message.getText()); topicPublisher.publish(message); } } catch (JMSException e) { System.out.println("Exception occurred: " + e.toString()); }
JMS example: Pub/Sub Subscriber (1/4) • import javax.jms.*; import javax.naming.*; public class SimpleTopicSubscriber{ public static void main(String[] args) { String topicName = null; Context jndiContext = null; TopicConnectionFactory topicConnectionFactory = null; TopicConnection topicConnection = null; TopicSession topicSession = null; Topic topic = null; TopicSubscriber topicSubscriber = null; TextMessage message = null; final int NUM_MSGS; final String MSG_TEXT = new String("Here is a message"); Properties env = new Properties(); // Specify the vendor-specific JDNI properties
JMS example: Pub/Sub Subscriber (2/4) • topicName = “Test Topic”;/* * Create a JNDI InitialContext */ try { jndiContext = new InitialContext(env); } catch (NamingException e) { System.out.println("Could not create JNDI " + "context: " + e.toString()); System.exit(1); } /* * Look up connection factory and topic. If either does * not exist, exit. */try { topicConnectionFactory = (TopicConnectionFactory) jndiContext.lookup("TopicConnectionFactory"); topic = (Topic) jndiContext.lookup(topicName); } catch (NamingException e) { System.out.println("JNDI lookup failed: " + e.toString()); System.exit(1); }
JMS example: Pub/Sub Subscriber (3/4) • try { topicConnection = topicConnectionFactory.createTopicConnection(user, psswd); topicSession = topicConnection.createTopicSession(false, Session.AUTO_ACKNOWLEDGE); topicSubscriber = topicSession.createSubscriber(topic); topicListener = new TextListener(); topicSubscriber.setMessageListener(topicListener); topicConnection.start(); System.out.println("To end program, enter Q or q, " + "then <return>"); //Read user input, exit when Q/q entered
JMS example: Pub/Sub Subscriber (4/4) • import javax.jms.*; public class TextListener implements MessageListener { public void onMessage(Message message) { TextMessage msg = null; try { if (message instanceof TextMessage) { msg = (TextMessage) message; System.out.println("Reading message: " + msg.getText()); } else { System.out.println("Message of wrong type: " + message.getClass().getName()); } } catch (JMSException e) { System.out.println("JMSException in onMessage(): " + e.toString()); }
JMS Application Anatomy • A Connection Factory is the object a client uses to create a connection with a provider. A connection factory encapsulates a set of connection configuration parameters that has been defined by an administrator. • A Session is a single-threaded context for producing and consuming messages. You use sessions to create message producers, message consumers, and messages.
JMS Application Anatomy JMS Client ConnectionFactory Message Server JNDI ConnectionFactories Destinations Connection Session Session
JNDI • import javax.naming.*; Properties env = new Properties();// Specify the vendor-specific JDNI propertiesjndiContext = new InitialContext(env); ….topicConnectionFactory = (TopicConnectionFactory) jndiContext.lookup("TopicConnectionFactory"); topic = (Topic) jndiContext.lookup(topicName); • JNDI – Java Naming and Directory InterfaceKind of “remote hashtable” – given a key (String), returns the value (Object) • JMS “Adminsitered objects”:ConnectionFactory : message server address, clustering, transport configuration, security Destination (Queue and Topic): data channel configuration, naming - are best maintained administratively rather than programmatically. The technology underlying these objects is likely to be very different from one implementation of the JMS API to another. Therefore, the management of these objects belongs with other administrative tasks that vary from provider to provider.
JNDI • Properties env = new Properties();// Specify the vendor-specific JDNI propertiesenv.put(Context.SECURITY_PRINCIPAL,”guest”);env.put(Context.INITIAL_CONTEXT_FACTORY, ”com.sun.jndi.ldap.LdapCtxFactory”);env.put(Context.PROVIDER_URL, “ldap://localhost:389/o=acme.com”);jndiContext = new InitialContext(env); • Alternatively, read JNDI environment properties from “jndi.properties” file.
JNDI Concepts • Names • “Test Topic” (JMS topic) • “www.ibm.com” (DNS address) • “/usr/local/java/bin/javac” (File name) • BindingThe association of a name with an object is called a binding. For example, a file name is bound to a file. • ReferenceCompact object representation, with information about how to access the object • ContextA context is a set of name-to-object bindings, with an associated naming convention.E.g. Unix naming convention, “/abc/def” • Directory • Attributes: Additional information on an object • Directory service: creating, adding, removing, and modifying the attributes • Search and Search filters
JMS Message: Headers • JMS Message: Headers + Properties + Payload • Headers: • JMSDestination • JMSDeliveryMode • JMSExpiration • JMSPriority • JMSMessageID : JMS provider • JMSTimestamp: JMS provider • JMSCorrelationID • JMSReplyTo • JMSRedelivered : JMS provider • JMSType
JMS Message: Properties and Types • Properties • message.setStringProperty(“Username”,”John Doe”); • Message Selectors • Can use both Property and Header fields • TopicSubscriber sub = session.createSubscriber(chatTopic,”Username != ‘William’); • Message Types • TextMessageA java.lang.String (for example, the contents of an eXtended Markup Language file) • MapMessageA set of name-value pairs, where names are String objects and values are primitive types in the Java programming language. The entries can be accessed sequentially by enumerator or randomly by name. The order of the entries is undefined. • BytesMessageA stream of uninterpreted bytes. This message type is for literally encoding a body to match an existing message format. • StreamMessageA stream of primitive values in the Java programming language. It is filled and read sequentially. • ObjectMessageA Serializable object in the Java programming language • MessageNothing. Composed of header fields and properties only. No body.
Assured Delivery: Message Acknowledgements • AutoAcknowledgetopicSession = topicConnection.createTopicSession(false, Session.AUTO_ACKNOWLEDGE); Implicitly after onMessage return • ClientAcknowledgetopicSession = topicConnection.createTopicSession(false, Session.CLIENT_ACKNOWLEDGE); • Inside onMessage() – for speedier feedback • On message group – message batch consumption in “all or nothing” fashion
Assured Delivery: Durable Subscription • topicSubscriber = topicSession.createDurableSubscriber(topic,”Some name”);
Assured Delivery: Persistence • “Store-and-Forward” • Remove upon Ack or Expiration Consumer Message Server Producer Ack Storage
Local transactions • Producer – Provider • Provider – Consumer
Bits & pieces • Temporary topics • Temporary queues Use in JMSReplyTo field • Queue browsing Any number of clients can connect to queue A message can be consumed by one only • “Pull” subscription .receive() instead of MessageListener • Dead Message Queue
Enterprise Application Integration Legacy System E-Mail gateway JMS Client JMS Client JMS Client JMS Server Vendor A JMS Server Vendor B JMS Client JMS Client JMS Client JMS Client Internet (http) Gateway JMS Client
JDBC • Uniform Java API to access any DB type SQL wrapper • Install database driver • Code snippets:Connection con = DriverManager.getConnection(url, "myLogin", "myPassword"); String createTableCoffees = "CREATE TABLE COFFEES " + "(COF_NAME VARCHAR(32), SUP_ID INTEGER, PRICE FLOAT, " + "SALES INTEGER, TOTAL INTEGER)"; Statement stmt = con.createStatement(); stmt.executeUpdate(createTableCoffees); stmt.executeUpdate("INSERT INTO COFFEES " + "VALUES ('French_Roast', 49, 8.99, 0, 0)"); ResultSet rs = stmt.executeQuery( "SELECT COF_NAME, PRICE FROM COFFEES"); while (rs.next()) { String s = rs.getString("COF_NAME"); float n = rs.getFloat("PRICE"); System.out.println(s + " " + n); }
Summary • Java Message Service (JMS) • Messaging vs Traditional networking: Asynchronous, decoupled • Publish/Subscribe, Point-to-Point messaging • Architecture • Centralized • Multicast • Hybrid • Samples • Assured delivery • Durable subscription • Persistent publishing • Acknowledged delivery • Enterprise Application Integration, Message-Oriented Middleware • JNDI • Administered object management; Naming and Directory Services. • JDBC • SQL wrapper; Database access