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.ObjectId;
034: import org.objectweb.carol.cmi.ServerConfigException;
035: import org.objectweb.carol.cmi.ServerIdFactory;
036: import org.objectweb.carol.cmi.configuration.TraceCmi;
037: import org.objectweb.carol.cmi.ha.RequestId;
038: import org.objectweb.jonas.ha.interceptor.HACurrentDelegateImpl;
039:
040: /**
041: * Generic part of the EJBObject implementation for replicated SFSBs
042: * @author Francisco Perez-Sorrosal (fpsorrosal@no-spam@fi.upm.es)
043: * @author Alberto Paz-Jimenez (apaz@no-spam@fi.upm.es)
044: */
045: public abstract class JRepStatefulRemote extends JSessionRemote {
046:
047: /**
048: * Constructor
049: * @param bf
050: * @throws RemoteException
051: */
052: public JRepStatefulRemote(JSessionFactory bf)
053: throws RemoteException {
054: super (bf);
055: if (TraceCmi.isDebugCmiHA()) {
056: TraceCmi.debugCmiHA("JRepStatefulRemote");
057: }
058: }
059:
060: /**
061: * preInvoke is called before any request.
062: * @param txa Transaction Attribute (Supports, Required, ...)
063: * @return A RequestCtx object
064: * @throws RemoteException Thrown when the method failed due to a
065: * system-level failure.
066: */
067: public RequestCtx preInvoke(int txa) throws RemoteException {
068: RequestCtx rctx = super .preInvoke(txa);
069: /* ******************REPLICATION CODE STARTS HERE*********************** */
070: preInvokeHook(rctx); // Replication algorithm link
071: /* **********************END OF REPLICATION CODE************************ */
072: return rctx;
073: }
074:
075: /**
076: * postInvoke is called after any request.
077: * @param rctx The RequestCtx that was returned at preInvoke()
078: * @param remove TODO
079: * @parem response The response that is going to be returned to the client
080: * (Needed by HA)
081: * @throws RemoteException Thrown when the method failed due to a
082: * system-level failure.
083: */
084: public void postInvoke(RequestCtx rctx, Object response,
085: boolean remove) throws RemoteException {
086: /* ******************REPLICATION CODE STARTS HERE*********************** */
087: try {
088: postInvokeHook(rctx, response, remove); // Replication algorithm link
089: /* **********************END OF REPLICATION CODE************************ */
090: } catch (Exception e) {
091: // COMPLETE: Handle errors
092: e.printStackTrace();
093: TraceCmi.error("Error calling postInvokeHook in sfsb.", e);
094: } finally {
095: super .postInvoke(rctx);
096: // We dont need the request anymore so remove it
097: removeCurrentRequest();
098: }
099: }
100:
101: /* ******************REPLICATION CODE STARTS HERE*********************** */
102:
103: // ------------------------------------------------------------------------
104: // Protected methods ------------------------------------------------------
105: // ------------------------------------------------------------------------
106: /**
107: * Injects the state of the bean if the cluster object id received in the
108: * request is in the current node. It extracts the object id passed through
109: * the interceptors from the request id included in the current HA context.
110: */
111: protected void injectState() {
112: HACurrentDelegateImpl current = HACurrentDelegateImpl
113: .getCurrent();
114: // We still need the request so do not remove it
115: RequestId reqId = (RequestId) current.getRequests().peek();
116: if (reqId != null) {
117: JRepUtil.injectState(reqId.getObjectId(),
118: (JStatefulSwitch) this .bs);
119: }
120: }
121:
122: /**
123: * Checks if there is a response associated with the current request id
124: * @return true if the current rquest id have an associated response
125: */
126: protected boolean hasResponse() {
127: HACurrentDelegateImpl current = HACurrentDelegateImpl
128: .getCurrent();
129: // We still need the request so do not remove it
130: RequestId reqId = (RequestId) current.getRequests().peek();
131: if (reqId != null) {
132: try {
133: return JRepUtil.hasBackupResponse(reqId);
134: } catch (Exception e) {
135: TraceCmi.error("Cannot check response : " + reqId, e);
136: return false;
137: }
138: } else {
139: return false;
140: }
141: }
142:
143: /**
144: * Obtain the response associated with the current request id.
145: * Returns null if there is not response associated with the current
146: * requestid
147: * IMPORTANT: This method remove the request id from the requests heap
148: * @return the response associated with the current request id
149: */
150: protected Object getResponse() {
151: Object response = null;
152:
153: HACurrentDelegateImpl current = HACurrentDelegateImpl
154: .getCurrent();
155: // We still need the request so do not remove it
156: RequestId reqId = (RequestId) current.getRequests().peek();
157: if (reqId != null) {
158: try {
159: response = JRepUtil.getRepMgr()
160: .getBackupResponse(reqId);
161: } catch (Exception e) {
162: TraceCmi.error("Cannot obtain response : " + reqId, e);
163: response = null;
164: }
165: } else {
166: response = null;
167: }
168:
169: // Remove the request
170: current.getRequests().pop();
171: return response;
172: }
173:
174: // ------------------------------------------------------------------------
175: // Private methods --------------------------------------------------------
176: // ------------------------------------------------------------------------
177:
178: /**
179: * preInvokeHook implements the hook to perform the required replication
180: * tasks before the bean context has been established. In this case, it
181: * saves the current state of the bean before perform the invocation, in the
182: * request context.
183: * @param rctx The RequestCtx that was returned at preInvoke()
184: * @throws RemoteException
185: */
186: private void preInvokeHook(RequestCtx rctx) throws RemoteException {
187: try {
188: // If the call is done from other JVM this is the root request
189: HACurrentDelegateImpl current = HACurrentDelegateImpl
190: .getCurrent();
191: // We still need the request so do not remove it
192: RequestId reqId = (RequestId) current.getRequests().peek();
193: // Discard external request ids
194: if (!reqId.getObjectId().getServerId().equals(
195: ServerIdFactory.getServerId())) {
196: current.getRequests().clear();
197: current.getRequests().push(reqId);
198: }
199:
200: JRepUtil.preInvokeHook(bs, reqId.getObjectId(), rctx);
201: } catch (ServerConfigException sce) {
202: TraceCmi.error("Unable to get Server Id.", sce);
203: } catch (EJBException e) {
204: e.printStackTrace();
205: TraceCmi.error("Unable to get sfsb state.", e);
206: }
207: }
208:
209: /**
210: * postInvokeHook implements the hook to perform the required replication
211: * tasks after the bean context has been established
212: * @param rctx The RequestCtx that was returned at preInvoke()
213: * @parem response The response that is going to be returned to the client
214: * @param remove true if it is an invocation to a remove method
215: */
216: private void postInvokeHook(RequestCtx rctx, Object response,
217: boolean remove) {
218: HACurrentDelegateImpl current = HACurrentDelegateImpl
219: .getCurrent();
220: RequestId reqId = null;
221: ObjectId clusterOId = null;
222:
223: reqId = (RequestId) current.getRequests().peek();
224: clusterOId = reqId.getObjectId();
225:
226: JRepUtil.postInvokeHook(rctx, clusterOId, bs, remove);
227:
228: // If this is the root request, then associate response with rootId
229: if (current.getRequests().size() == 1) {
230: try {
231: JRepUtil.getRepMgr().addResponse(reqId, response);
232: } catch (Exception e) {
233: e.printStackTrace();
234: TraceCmi.error("unable to obtain replication manager.",
235: e);
236: }
237: }
238: }
239:
240: /**
241: * Removes the curren request from the requests heap
242: */
243: private void removeCurrentRequest() {
244: HACurrentDelegateImpl current = HACurrentDelegateImpl
245: .getCurrent();
246: current.getRequests().pop();
247: }
248:
249: /* **********************END OF REPLICATION CODE************************ */
250: }
|