View Javadoc

1   /*$Id: CeaApplicationDispatcher.java,v 1.5 2006/01/04 09:52:31 clq2 Exp $
2    * Created on 25-Feb-2004
3    *
4    * Copyright (C) AstroGrid. All rights reserved.
5    *
6    * This software is published under the terms of the AstroGrid
7    * Software License version 1.2, a copy of which has been included
8    * with this distribution in the LICENSE.txt file.
9    *
10  **/
11  package org.astrogrid.jes.jobscheduler.dispatcher;
12  
13  import org.astrogrid.applications.delegate.CommonExecutionConnectorClient;
14  import org.astrogrid.applications.delegate.DelegateFactory;
15  import org.astrogrid.component.descriptor.ComponentDescriptor;
16  import org.astrogrid.jes.JesException;
17  import org.astrogrid.jes.delegate.JesDelegateFactory;
18  import org.astrogrid.jes.delegate.JobMonitor;
19  import org.astrogrid.jes.jobscheduler.Dispatcher;
20  import org.astrogrid.jes.jobscheduler.Locator;
21  import org.astrogrid.jes.types.v1.cea.axis.JobIdentifierType;
22  import org.astrogrid.jes.util.JesUtil;
23  import org.astrogrid.workflow.beans.v1.Tool;
24  import org.astrogrid.workflow.beans.v1.Workflow;
25  
26  import org.apache.commons.logging.Log;
27  import org.apache.commons.logging.LogFactory;
28  
29  import java.net.URI;
30  import java.net.URLConnection;
31  import java.util.ArrayList;
32  import java.util.Arrays;
33  import java.util.List;
34  
35  import junit.framework.Test;
36  import junit.framework.TestCase;
37  import junit.framework.TestSuite;
38  
39  /*** Implementation of a Dispactcher that calls an cea  web service to execute a job step.
40   * @author Noel Winstanley nw@jb.man.ac.uk 25-Feb-2004
41   *
42   */
43  public  class CeaApplicationDispatcher implements Dispatcher, ComponentDescriptor {
44     private static final Log logger =
45        LogFactory.getLog(CeaApplicationDispatcher.class);
46     /*** Configuration component for Application Controller Dispatcher
47      * @author Noel Winstanley nw@jb.man.ac.uk 07-Mar-2004
48      *
49      */
50     public interface Endpoints {
51        URI monitorEndpoint();
52        URI resultListenerEndpoint();
53     }
54     /*** Construct a new ApplicationControllerDispatcher
55      * @param locator tool locator component to use to resolve endpoints
56      * @param endpoint configuration component that specifies the endpoint of the JobMonitor service. This is used by the
57      ApplicationController to
58      * return execution information back to the JES server.
59      */
60     public CeaApplicationDispatcher(Locator locator, Endpoints endpoint) {
61        this.locator = locator;
62        this.monitorURI = endpoint.monitorEndpoint();
63        this.resultListenerURI = endpoint.resultListenerEndpoint();
64        assert monitorURI != null;
65        assert resultListenerURI != null;
66        logger.info("monitor URL set to " + monitorURI.toString());
67        logger.info("result URL set to " + resultListenerURI.toString());
68     }
69     /*** tool locator component */
70     protected final Locator locator;
71     /*** endpoint of local jobmonitor service - used as a callback */
72     protected final URI monitorURI;
73     /*** endpoint of local result listener servuce - again, used as a callback */
74     protected final URI resultListenerURI;
75  
76  
77     public void dispatchStep(Workflow job, Tool tool,String stepId) throws JesException {
78  
79        String[] toolLocations = locator.locateTool(tool);
80        JobIdentifierType id = JesUtil.createJobId(job.getJobExecutionRecord().getJobId(), stepId);
81        boolean connected = false;
82        if (logger.isDebugEnabled()) {
83            logger.debug("Will attempt to connect to " + Arrays.asList(toolLocations));
84        }
85        List exceptions = new ArrayList();
86        for (int i = 0; i < toolLocations.length && ! connected ; i++) { // try each one in the list, until something sticks.
87            try {
88                logger.debug("Creating a job on CEA server at " + toolLocations[i] +
89                             " for " + tool.getName() + ", "+ id.getValue());
90                CommonExecutionConnectorClient appController =    DelegateFactory.createDelegate(toolLocations[i]);
91                String applicationId = appController.init(tool,id);
92                logger.debug("Registering results listener " + resultListenerURI + " with " + toolLocations[i]);
93                appController.registerResultsListener(applicationId,resultListenerURI);
94                logger.debug("Registering progress listener " + monitorURI + " with " + toolLocations[i]);
95                appController.registerProgressListener(applicationId,monitorURI);
96                logger.debug("Activating the job on " + toolLocations[i]);
97                appController.execute(applicationId);
98                logger.debug("The job on " + toolLocations[i] + " was dispatched successfully.");
99                connected = true; // signal that we've connected to a cea, so no need to keep looping.
100           }
101           catch (Throwable e) {
102               logger.warn("Failed to communicate or initialize application with CEA Server",e);
103               exceptions.add(e); // only want to fail when we can't connect to any of them -
104                                  // but need to preserve the exceptions, for reporting in case all fail.
105           }
106       }
107       if (! connected) {// exhausted all possibilities, so fail
108           String str = "Failed to communicate or initialize application with any CEA Server that provides this application:" +
109           Arrays.asList(toolLocations);
110           Throwable cause = null;
111           if (exceptions.size() == 1) {
112               cause = (Throwable)exceptions.get(0);
113           } else if (exceptions.size() > 1) {
114               cause = new AggregateException((Throwable[])exceptions.toArray(new Throwable[]{}));
115           }
116           logger.warn(str,cause);
117          throw new JesException(str,cause);
118       }
119 
120    }
121 
122    /***
123     * @see org.astrogrid.jes.component.ComponentDescriptor#getName()
124     */
125    public String getName() {
126       return "ApplicationController Dispatcher";
127    }
128 
129    /***
130     * @see org.astrogrid.jes.component.ComponentDescriptor#getDescription()
131     */
132    public String getDescription() {
133       return "Dispatcher that executes job steps by calling application controllers"
134          + " Configured to tell application controllers to call back to:\n"
135          + monitorURI.toString();
136    }
137 
138    /***
139     * @see org.astrogrid.jes.component.ComponentDescriptor#getInstallationTest()
140     */
141    public Test getInstallationTest() {
142       TestSuite suite = new TestSuite("Tests for ApplicationControllerDispatcher");
143       suite.addTest(new InstallationTest("testCanConnectMonitorURL"));
144       suite.addTest(new InstallationTest("testCanCallMonitorURL"));
145       return suite;
146    }
147 
148    protected class InstallationTest extends TestCase {
149       public InstallationTest(String s) {
150          super(s);
151       }
152       public void testCanConnectMonitorURL() throws Exception {
153          URLConnection conn = monitorURI.toURL().openConnection();
154          assertNotNull(conn);
155          conn.connect();
156 
157       }
158       public void testCanCallMonitorURL() throws Exception {
159          JobMonitor mon = JesDelegateFactory.createJobMonitor(monitorURI.toString());
160          assertNotNull(mon);
161          // call, with null parameters. will be ignored by other end - if it gets there. we're checking it gets there..
162          mon.monitorJob(null, null);
163       }
164    }
165 
166 
167 
168 }
169 
170 /*
171 $Log: CeaApplicationDispatcher.java,v $
172 Revision 1.5  2006/01/04 09:52:31  clq2
173 jes-gtr-1462
174 
175 Revision 1.4.42.1  2005/12/02 11:38:48  gtr
176 I changed the logging slightly, logging more to do with transactions on other services.
177 
178 Revision 1.4  2005/04/25 12:13:54  clq2
179 jes-nww-776-again
180 
181 Revision 1.3.4.1  2005/04/11 13:56:20  nw
182 organized imports
183 
184 Revision 1.3  2005/04/01 10:24:19  nw
185 improved logging of cea connect failures
186 
187 Revision 1.2  2005/03/13 07:13:39  clq2
188 merging jes-nww-686 common-nww-686 workflow-nww-996 scripting-nww-995 cea-nww-994
189 
190 Revision 1.1.2.2  2005/03/11 15:21:35  nw
191 adjusted locator so that it returns a list of endpoints to connect to.
192 we can get round-robin by shuffling the list.
193 dispatcher tries each endpoint in the list until can connect to one wihout throwing an exception.
194 
195 Revision 1.1.2.1  2005/03/11 14:04:03  nw
196 added new kinds of dispatcher.
197 
198 Revision 1.19  2004/08/13 09:07:58  nw
199 tidied imports
200 
201 Revision 1.18  2004/08/09 17:31:11  nw
202 adjusted interface, to work better with dynamically-generated states.
203 
204 Revision 1.17  2004/08/03 16:31:25  nw
205 simplified interface to dispatcher and locator components.
206 removed redundant implementations.
207 
208 Revision 1.16  2004/07/30 15:42:34  nw
209 merged in branch nww-itn06-bz#441 (groovy scripting)
210 
211 Revision 1.15.20.1  2004/07/30 15:10:04  nw
212 removed policy-based implementation,
213 adjusted tests, etc to use groovy implementation
214 
215 Revision 1.15  2004/07/09 09:30:28  nw
216 merged in scripting workflow interpreter from branch
217 nww-x-workflow-extensions
218 
219 Revision 1.14  2004/07/02 09:07:58  nw
220 added in results listener
221 
222 Revision 1.13  2004/07/01 21:15:00  nw
223 added results-listener interface to jes
224 
225 Revision 1.12  2004/07/01 11:19:05  nw
226 updated interface with cea - part of cea componentization
227 
228 Revision 1.11  2004/05/27 09:49:42  nw
229 improved exception reporting 'when applications go bad'
230 
231 Revision 1.10  2004/04/08 14:43:26  nw
232 added delete and abort job functionality
233 
234 Revision 1.9  2004/03/24 08:05:08  pah
235 call the new CommonExecutionConnector Delegate
236 
237 Revision 1.8  2004/03/15 23:45:07  nw
238 improved javadoc
239 
240 Revision 1.7  2004/03/15 01:30:45  nw
241 factored component descriptor out into separate package
242 
243 Revision 1.6  2004/03/12 15:32:14  nw
244 improved logging
245 
246 Revision 1.5  2004/03/07 21:04:39  nw
247 merged in nww-itn05-pico - adds picocontainer
248 
249 Revision 1.4.4.1  2004/03/07 20:41:06  nw
250 added component descriptor interface impl,
251 refactored any primitive types passed into constructor
252 
253 Revision 1.4  2004/03/05 16:16:23  nw
254 worked now object model through jes.
255 implemented basic scheduling policy
256 removed internal facade
257 
258 Revision 1.3  2004/03/04 01:57:35  nw
259 major refactor.
260 upgraded to latest workflow object model.
261 removed internal facade
262 replaced community snippet with objects
263 
264 Revision 1.2  2004/02/27 00:46:03  nw
265 merged branch nww-itn05-bz#91
266 
267 Revision 1.1.2.1  2004/02/27 00:27:07  nw
268 rearranging code
269 
270 */