View Javadoc

1   /***
2    *
3    * Copyright 2005 LogicBlaze, Inc.
4    *
5    * Licensed under the Apache License, Version 2.0 (the "License");
6    * you may not use this file except in compliance with the License.
7    * You may obtain a copy of the License at
8    *
9    * http://www.apache.org/licenses/LICENSE-2.0
10   *
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the License for the specific language governing permissions and
15   * limitations under the License.
16   *
17   **/
18  package org.logicblaze.lingo.jms.marshall;
19  
20  import org.apache.commons.logging.Log;
21  import org.apache.commons.logging.LogFactory;
22  import org.logicblaze.lingo.LingoInvocation;
23  import org.logicblaze.lingo.jms.Requestor;
24  import org.springframework.remoting.support.RemoteInvocation;
25  import org.springframework.remoting.support.RemoteInvocationResult;
26  
27  import javax.jms.JMSException;
28  import javax.jms.Message;
29  import javax.jms.ObjectMessage;
30  import javax.jms.Session;
31  import javax.jms.TextMessage;
32  
33  import java.io.Serializable;
34  
35  /***
36   * Represents the strategy of marshalling of requests and responses in and out
37   * of JMS messages
38   * 
39   * @version $Revision: 1.5 $
40   */
41  public class DefaultMarshaller implements Marshaller {
42  
43      private static final Log log = LogFactory.getLog(DefaultMarshaller.class);
44  
45      private boolean ignoreInvalidMessages;
46  
47      private String stickySessionID;
48  
49      public Message createRequestMessage(Requestor requestor, LingoInvocation invocation) throws JMSException {
50          ObjectMessage message = requestor.getSession().createObjectMessage(invocation);
51          appendMessageHeaders(message, requestor, invocation);
52          return message;
53      }
54  
55      public Message createResponseMessage(Session session, RemoteInvocationResult result, Message requestMessage) throws JMSException {
56          ObjectMessage answer = session.createObjectMessage(result);
57          addResponseMessageHeaders(answer, result, requestMessage);
58          return answer;
59      }
60  
61      public RemoteInvocationResult extractInvocationResult(Message message) throws JMSException {
62          handleInvocationResultHeaders(message);
63          if (message instanceof ObjectMessage) {
64              ObjectMessage objectMessage = (ObjectMessage) message;
65              Object body = objectMessage.getObject();
66              if (body instanceof RemoteInvocationResult) {
67                  return (RemoteInvocationResult) body;
68              }
69          }
70          return onInvalidClientMessage(message);
71      }
72  
73      public RemoteInvocation readRemoteInvocation(Message message) throws JMSException {
74          handleInvocationHeaders(message);
75          if (message instanceof ObjectMessage) {
76              ObjectMessage objectMessage = (ObjectMessage) message;
77              Object body = objectMessage.getObject();
78              if (body instanceof RemoteInvocation) {
79                  return (RemoteInvocation) body;
80              }
81          }
82          return onInvalidMessage(message);
83      }
84  
85      public Message createObjectMessage(Session session, Object value) throws JMSException {
86          Message message = null;
87          if (value instanceof String) {
88              message = session.createTextMessage((String) value);
89          }
90          else {
91              message = session.createObjectMessage((Serializable) value);
92          }
93          appendMessageHeaders(message, session, value);
94          return message;
95      }
96  
97      public Object readMessage(Message message) throws JMSException {
98          handleMessageHeaders(message);
99          if (message instanceof ObjectMessage) {
100             ObjectMessage objectMessage = (ObjectMessage) message;
101             return objectMessage.getObject();
102         }
103         else if (message instanceof TextMessage) {
104             TextMessage textMessage = (TextMessage) message;
105             return textMessage.getText();
106         }
107         return onInvalidMessage(message);
108     }
109 
110     // Properties
111     // -------------------------------------------------------------------------
112     public boolean isIgnoreInvalidMessages() {
113         return ignoreInvalidMessages;
114     }
115 
116     /***
117      * Sets whether invalidly formatted messages should be silently ignored or
118      * not
119      */
120     public void setIgnoreInvalidMessages(boolean ignoreInvalidMessages) {
121         this.ignoreInvalidMessages = ignoreInvalidMessages;
122     }
123 
124     // Implementation methods
125     // -------------------------------------------------------------------------
126     protected RemoteInvocationResult onInvalidClientMessage(Message message) throws JMSException {
127         throw new JMSException("Invalid response message: " + message);
128     }
129 
130     /***
131      * Handle invalid messages by just logging, though a different
132      * implementation may wish to throw exceptions
133      */
134     protected RemoteInvocation onInvalidMessage(Message message) {
135         String text = "Invalid message will be discarded: " + message;
136         log.info(text);
137         if (!ignoreInvalidMessages) {
138             throw new RuntimeException(text);
139         }
140         return null;
141     }
142 
143     /***
144      * A strategy method for derived classes to allow them a plugin point to
145      * perform custom header processing
146      */
147     protected void appendMessageHeaders(Message message, Requestor requestor, LingoInvocation invocation) throws JMSException {
148         if (invocation.getMetadata().isStateful()) {
149             message.setStringProperty("JMSXGroupID", getStickySessionID());
150         }
151     }
152 
153     protected void appendMessageHeaders(Message message, Session session, Object value) {
154     }
155 
156     protected String getStickySessionID() {
157         if (stickySessionID == null) {
158             stickySessionID = "hey";
159             // TODO
160             throw new RuntimeException("TODO: Not Implemented Yet!");
161         }
162         return stickySessionID;
163     }
164 
165     /***
166      * A strategy for derived classes to allow them to plug in custom header
167      * processing for responses
168      */
169     protected void addResponseMessageHeaders(ObjectMessage answer, RemoteInvocationResult result, Message requestMessage) throws JMSException {
170     }
171 
172     /***
173      * A strategy method to allow derived classes to process the headers in a
174      * special way
175      */
176     protected void handleInvocationHeaders(Message message) {
177     }
178 
179     /***
180      * A strategy method to allow derived classes to process the headers in a
181      * special way
182      */
183     protected void handleInvocationResultHeaders(Message message) {
184     }
185 
186     /***
187      * A strategy method to allow derived classes to process the headers in a
188      * special way
189      */
190     protected void handleMessageHeaders(Message message) {
191     }
192 
193 }