001: /**
002: * JOnAS: Java(TM) Open Application Server
003: * Copyright (C) 2006 Bull S.A.S.
004: * Contact: jonas-team@objectweb.org
005: * Copyright (C) 2006 Distributed Systems Lab.
006: * Universidad Polit??cnica de Madrid (Spain)
007: * Contact: http://lsd.ls.fi.upm.es/lsd
008: *
009: * This library is free software; you can redistribute it and/or
010: * modify it under the terms of the GNU Lesser General Public
011: * License as published by the Free Software Foundation; either
012: * version 2.1 of the License, or any later version.
013: *
014: * This library is distributed in the hope that it will be useful,
015: * but WITHOUT ANY WARRANTY; without even the implied warranty of
016: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
017: * Lesser General Public License for more details.
018: *
019: * You should have received a copy of the GNU Lesser General Public
020: * License along with this library; if not, write to the Free Software
021: * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
022: * USA
023: *
024: * --------------------------------------------------------------------------
025: *
026: * --------------------------------------------------------------------------
027: */package org.objectweb.jonas_ejb.container;
028:
029: import java.rmi.RemoteException;
030:
031: import javax.ejb.EJBException;
032:
033: import org.objectweb.carol.cmi.ServerConfigException;
034: import org.objectweb.carol.cmi.ServerIdFactory;
035: import org.objectweb.carol.cmi.configuration.TraceCmi;
036: import org.objectweb.carol.cmi.ha.RequestId;
037: import org.objectweb.jonas.ha.interceptor.HACurrentDelegateImpl;
038:
039: /**
040: * Generic part of the EJBObject implementation for replicated SSBs
041: * @author Francisco Perez-Sorrosal (fpsorrosal@no-spam@fi.upm.es)
042: * @author Alberto Paz-Jimenez (apaz@no-spam@fi.upm.es)
043: */
044: public abstract class JRepStatelessRemote extends JSessionRemote {
045:
046: /**
047: * Constructor
048: * @param bf
049: * @throws RemoteException
050: */
051: public JRepStatelessRemote(JSessionFactory bf)
052: throws RemoteException {
053: super (bf);
054: if (TraceCmi.isDebugCmiHA()) {
055: TraceCmi.debugCmiHA("JRepStatelessRemote");
056: }
057: }
058:
059: /**
060: * preInvoke is called before any request.
061: * @param txa Transaction Attribute (Supports, Required, ...)
062: * @return A RequestCtx object
063: * @throws RemoteException Thrown when the method failed due to a
064: * system-level failure.
065: */
066: public RequestCtx preInvoke(int txa) throws RemoteException {
067: RequestCtx rctx = super .preInvoke(txa);
068: /* ******************REPLICATION CODE STARTS HERE*********************** */
069: preInvokeHook(rctx); // Replication algorithm link
070: /* **********************END OF REPLICATION CODE************************ */
071: return rctx;
072: }
073:
074: /**
075: * postInvoke is called after any request.
076: * @param rctx The RequestCtx that was returned at preInvoke()
077: * @param remove TODO
078: * @parem response The response that is going to be returned to the client
079: * (Needed by HA)
080: * @throws RemoteException Thrown when the method failed due to a
081: * system-level failure.
082: */
083: public void postInvoke(RequestCtx rctx, Object response)
084: throws RemoteException {
085: /* ******************REPLICATION CODE STARTS HERE*********************** */
086: try {
087: postInvokeHook(response); // Replication algorithm link
088: /* **********************END OF REPLICATION CODE************************ */
089: } catch (Exception e) {
090: // COMPLETE: Handle errors
091: e.printStackTrace();
092: TraceCmi.error("Error calling postInvokeHook in sfsb.", e);
093: } finally {
094: super .postInvoke(rctx);
095: // We dont need the request anymore so remove it
096: removeCurrentRequest();
097: }
098: }
099:
100: /**
101: * Checks if there is a response associated with the current request id
102: * @return true if the current rquest id have an associated response
103: */
104: protected boolean hasResponse() {
105: HACurrentDelegateImpl current = HACurrentDelegateImpl
106: .getCurrent();
107: // We still need the request so do not remove it
108: RequestId reqId = (RequestId) current.getRequests().peek();
109: if (reqId != null) {
110: try {
111: return JRepUtil.hasBackupResponse(reqId);
112: } catch (Exception e) {
113: TraceCmi.error("Cannot check response : " + reqId, e);
114: return false;
115: }
116: } else {
117: return false;
118: }
119: }
120:
121: /**
122: * Obtain the response associated with the current request id.
123: * Returns null if there is not response associated with the current
124: * requestid
125: * IMPORTANT: This method remove the request id from the requests heap
126: * @return the response associated with the current request id
127: */
128: protected Object getResponse() {
129: Object response = null;
130:
131: HACurrentDelegateImpl current = HACurrentDelegateImpl
132: .getCurrent();
133: // We still need the request so do not remove it
134: RequestId reqId = (RequestId) current.getRequests().peek();
135: if (reqId != null) {
136: try {
137: response = JRepUtil.getRepMgr()
138: .getBackupResponse(reqId);
139: } catch (Exception e) {
140: TraceCmi.error("Cannot obtain response : " + reqId, e);
141: response = null;
142: }
143: } else {
144: response = null;
145: }
146:
147: // Remove the request
148: current.getRequests().pop();
149: return response;
150: }
151:
152: // ------------------------------------------------------------------------
153: // Private methods --------------------------------------------------------
154: // ------------------------------------------------------------------------
155:
156: /**
157: * preInvokeHook implements the hook to perform the required replication
158: * tasks before the bean context has been established. In this case, it
159: * saves the current state of the bean before perform the invocation, in the
160: * request context.
161: * @param rctx The RequestCtx that was returned at preInvoke()
162: * @throws RemoteException
163: */
164: private void preInvokeHook(RequestCtx rctx) throws RemoteException {
165: try {
166: // If the call is done from other JVM this is the root request
167: HACurrentDelegateImpl current = HACurrentDelegateImpl
168: .getCurrent();
169: // We still need the request so do not remove it
170: RequestId reqId = (RequestId) current.getRequests().peek();
171: // Discard external request ids
172: if (!reqId.getObjectId().getServerId().equals(
173: ServerIdFactory.getServerId())) {
174: current.getRequests().clear();
175: current.getRequests().push(reqId);
176: }
177: } catch (ServerConfigException sce) {
178: TraceCmi.error("Unable to get Server Id.", sce);
179: } catch (EJBException e) {
180: e.printStackTrace();
181: TraceCmi.error("Unable to get sfsb state.", e);
182: }
183: }
184:
185: /**
186: * postInvokeHook implements the hook to perform the required replication
187: * tasks after the bean context has been established
188: * @param rctx The RequestCtx that was returned at preInvoke()
189: * @parem response The response that is going to be returned to the client
190: * @param remove true if it is an invocation to a remove method
191: */
192: private void postInvokeHook(Object response) {
193: HACurrentDelegateImpl current = HACurrentDelegateImpl
194: .getCurrent();
195:
196: RequestId rootId = (RequestId) current.getRequests().get(0);
197:
198: // If this is the root request, then associate response with rootId
199: if (current.getRequests().size() == 1) {
200: try {
201: JRepUtil.getRepMgr().addResponse(rootId, response);
202: } catch (Exception e) {
203: e.printStackTrace();
204: TraceCmi.error("unable to obtain replication manager.",
205: e);
206: }
207: }
208: }
209:
210: /**
211: * Removes the curren request from the requests heap
212: */
213: private void removeCurrentRequest() {
214: HACurrentDelegateImpl current = HACurrentDelegateImpl
215: .getCurrent();
216: current.getRequests().pop();
217: }
218: }
|