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: public abstract class JRepEntityRemote extends JEntityRemote {
040:
041: public JRepEntityRemote(JEntityFactory bf) throws RemoteException {
042: super (bf);
043: if (TraceCmi.isDebugCmiHA()) {
044: TraceCmi.debugCmiHA("JRepEntityRemote");
045: }
046: }
047:
048: /**
049: * preInvoke is called before any request.
050: * @param txa Transaction Attribute (Supports, Required, ...)
051: * @return A RequestCtx object
052: * @throws RemoteException Thrown when the method failed due to a
053: * system-level failure.
054: */
055: public RequestCtx preInvoke(int txa) throws RemoteException {
056: RequestCtx rctx = super .preInvoke(txa);
057: /* ******************REPLICATION CODE STARTS HERE*********************** */
058: preInvokeHook(rctx); // Replication algorithm link
059: /* **********************END OF REPLICATION CODE************************ */
060: return rctx;
061: }
062:
063: /**
064: * postInvoke is called after any request.
065: * @param rctx The RequestCtx that was returned at preInvoke()
066: * @param remove TODO
067: * @parem response The response that is going to be returned to the client
068: * (Needed by HA)
069: * @throws RemoteException Thrown when the method failed due to a
070: * system-level failure.
071: */
072: public void postInvoke(RequestCtx rctx, JEntityContext bctx,
073: Object response) throws RemoteException {
074: /* ******************REPLICATION CODE STARTS HERE*********************** */
075: try {
076: postInvokeHook(bctx, response); // Replication algorithm link
077: /* **********************END OF REPLICATION CODE************************ */
078: } catch (Exception e) {
079: // COMPLETE: Handle errors
080: e.printStackTrace();
081: TraceCmi.error("Error calling postInvokeHook in sfsb.", e);
082: } finally {
083: super .postInvoke(rctx);
084: // We dont need the request anymore so remove it
085: removeCurrentRequest();
086: }
087: }
088:
089: /**
090: * Checks if there is a response associated with the current request id
091: * @return true if the current rquest id have an associated response
092: */
093: protected boolean hasResponse() {
094: HACurrentDelegateImpl current = HACurrentDelegateImpl
095: .getCurrent();
096: // We still need the request so do not remove it
097: RequestId reqId = (RequestId) current.getRequests().peek();
098: if (reqId != null) {
099: try {
100: return JRepUtil.hasBackupResponse(reqId);
101: } catch (Exception e) {
102: TraceCmi.error("Cannot check response : " + reqId, e);
103: return false;
104: }
105: } else {
106: return false;
107: }
108: }
109:
110: /**
111: * Obtain the response associated with the current request id.
112: * Returns null if there is not response associated with the current
113: * requestid
114: * IMPORTANT: This method remove the request id from the requests heap
115: * @return the response associated with the current request id
116: */
117: protected Object getResponse() {
118: Object response = null;
119:
120: HACurrentDelegateImpl current = HACurrentDelegateImpl
121: .getCurrent();
122: // We still need the request so do not remove it
123: RequestId reqId = (RequestId) current.getRequests().peek();
124: if (reqId != null) {
125: try {
126: response = JRepUtil.getRepMgr()
127: .getBackupResponse(reqId);
128: } catch (Exception e) {
129: TraceCmi.error("Cannot obtain response : " + reqId, e);
130: response = null;
131: }
132: } else {
133: response = null;
134: }
135:
136: // Remove the request
137: current.getRequests().pop();
138: return response;
139: }
140:
141: // ------------------------------------------------------------------------
142: // Private methods --------------------------------------------------------
143: // ------------------------------------------------------------------------
144:
145: /**
146: * preInvokeHook implements the hook to perform the required replication
147: * tasks before the bean context has been established. In this case, it
148: * saves the current state of the bean before perform the invocation, in the
149: * request context.
150: * @param rctx The RequestCtx that was returned at preInvoke()
151: * @throws RemoteException
152: */
153: private void preInvokeHook(RequestCtx rctx) throws RemoteException {
154: try {
155: // If the call is done from other JVM this is the root request
156: HACurrentDelegateImpl current = HACurrentDelegateImpl
157: .getCurrent();
158: // We still need the request so do not remove it
159: RequestId reqId = (RequestId) current.getRequests().peek();
160: // Discard external request ids
161: if (!reqId.getObjectId().getServerId().equals(
162: ServerIdFactory.getServerId())) {
163: current.getRequests().clear();
164: current.getRequests().push(reqId);
165: }
166: } catch (ServerConfigException sce) {
167: TraceCmi.error("Unable to get Server Id.", sce);
168: } catch (EJBException e) {
169: e.printStackTrace();
170: TraceCmi.error("Unable to get sfsb state.", e);
171: }
172: }
173:
174: /**
175: * postInvokeHook implements the hook to perform the required replication
176: * tasks after the bean context has been established
177: * @param rctx The RequestCtx that was returned at preInvoke()
178: * @parem response The response that is going to be returned to the client
179: * @param remove true if it is an invocation to a remove method
180: */
181: private void postInvokeHook(JEntityContext bctx, Object response) {
182: HACurrentDelegateImpl current = HACurrentDelegateImpl
183: .getCurrent();
184:
185: RequestId rootId = (RequestId) current.getRequests().get(0);
186: JRepUtil.addEntityBean(bctx, rootId);
187:
188: // If this is the root request, then associate response with rootId
189: if (current.getRequests().size() == 1) {
190: try {
191: JRepUtil.getRepMgr().addResponse(rootId, response);
192: } catch (Exception e) {
193: e.printStackTrace();
194: TraceCmi.error("unable to obtain replication manager.",
195: e);
196: }
197: }
198: }
199:
200: /**
201: * Removes the curren request from the requests heap
202: */
203: private void removeCurrentRequest() {
204: HACurrentDelegateImpl current = HACurrentDelegateImpl
205: .getCurrent();
206: current.getRequests().pop();
207: }
208:
209: }
|