Home » synapse-1.2-src » org.apache.synapse.endpoints » [javadoc | source]

    1   /*
    2    *  Licensed to the Apache Software Foundation (ASF) under one
    3    *  or more contributor license agreements.  See the NOTICE file
    4    *  distributed with this work for additional information
    5    *  regarding copyright ownership.  The ASF licenses this file
    6    *  to you under the Apache License, Version 2.0 (the
    7    *  "License"); you may not use this file except in compliance
    8    *  with the License.  You may obtain a copy of the License at
    9    *
   10    *   http://www.apache.org/licenses/LICENSE-2.0
   11    *
   12    *  Unless required by applicable law or agreed to in writing,
   13    *  software distributed under the License is distributed on an
   14    *   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
   15    *  KIND, either express or implied.  See the License for the
   16    *  specific language governing permissions and limitations
   17    *  under the License.
   18    */
   19   
   20   package org.apache.synapse.endpoints;
   21   
   22   import org.apache.axis2.clustering.ClusterManager;
   23   import org.apache.axis2.context.ConfigurationContext;
   24   import org.apache.commons.logging.Log;
   25   import org.apache.commons.logging.LogFactory;
   26   import org.apache.synapse.FaultHandler;
   27   import org.apache.synapse.MessageContext;
   28   import org.apache.synapse.SynapseConstants;
   29   import org.apache.synapse.core.axis2.Axis2MessageContext;
   30   
   31   import java.util.List;
   32   
   33   /**
   34    * FailoverEndpoint can have multiple child endpoints. It will always try to send messages to
   35    * current endpoint. If the current endpoint is failing, it gets another active endpoint from the
   36    * list and make it the current endpoint. Then the message is sent to the current endpoint and if
   37    * it fails, above procedure repeats until there are no active endpoints. If all endpoints are
   38    * failing and parent endpoint is available, this will delegate the problem to the parent endpoint.
   39    * If parent endpoint is not available it will pop the next FaultHandler and delegate the problem
   40    * to that.
   41    */
   42   public class FailoverEndpoint implements Endpoint {
   43   
   44       private static final Log log = LogFactory.getLog(FailoverEndpoint.class);
   45   
   46       /**
   47        * Name of the endpoint. Used for named endpoints which can be referred using the key attribute
   48        * of indirect endpoints.
   49        */
   50       private String name = null;
   51       /**
   52        * List of child endpoints. Failover sending is done among these. Any object implementing the
   53        * Endpoint interface can be a child.
   54        */
   55       private List<Endpoint> endpoints = null;
   56   
   57       /**
   58        * Endpoint for which currently sending the SOAP traffic.
   59        */
   60       private Endpoint currentEndpoint = null;
   61   
   62       /**
   63        * Parent endpoint of this endpoint if this used inside another endpoint. Possible parents are
   64        * LoadbalanceEndpoint, SALoadbalanceEndpoint and FailoverEndpoint objects. But use of
   65        * SALoadbalanceEndpoint as the parent is the logical scenario.
   66        */
   67       private Endpoint parentEndpoint = null;
   68   
   69       /**
   70        * The endpoint context , place holder for keep any runtime states related to the endpoint
   71        */
   72       private final EndpointContext endpointContext = new EndpointContext();
   73   
   74       public void send(MessageContext synMessageContext) {
   75   
   76           if (log.isDebugEnabled()) {
   77               log.debug("Start : Failover Endpoint");
   78           }
   79   
   80           boolean isClusteringEnable = false;
   81           // get Axis2 MessageContext and ConfigurationContext
   82           org.apache.axis2.context.MessageContext axisMC =
   83                   ((Axis2MessageContext) synMessageContext).getAxis2MessageContext();
   84           ConfigurationContext cc = axisMC.getConfigurationContext();
   85   
   86           //The check for clustering environment 
   87   
   88           ClusterManager clusterManager = cc.getAxisConfiguration().getClusterManager();
   89           if (clusterManager != null &&
   90                   clusterManager.getContextManager() != null) {
   91               isClusteringEnable = true;
   92           }
   93   
   94           String endPointName = this.getName();
   95           if (endPointName == null) {
   96   
   97               if (log.isDebugEnabled() && isClusteringEnable) {
   98                   log.warn("In a clustering environment , the endpoint  name should be specified" +
   99                           "even for anonymous endpoints. Otherwise , the clustering would not be " +
  100                           "functioned correctly if there are more than one anonymous endpoints. ");
  101               }
  102               endPointName = SynapseConstants.ANONYMOUS_ENDPOINT;
  103           }
  104   
  105           if (isClusteringEnable) {
  106               // if this is a cluster environment , then set configuration context to endpoint context
  107               if (endpointContext.getConfigurationContext() == null) {
  108                   endpointContext.setConfigurationContext(cc);
  109                   endpointContext.setContextID(endPointName);
  110               }
  111           }
  112   
  113           // We have to build the envelop if we are supporting failover.
  114           // Failover should sent the original message multiple times if failures occur. So we have to
  115           // access the envelop multiple times.        
  116           synMessageContext.getEnvelope().build();
  117   
  118           if (currentEndpoint.isActive(synMessageContext)) {
  119               currentEndpoint.send(synMessageContext);
  120           } else {
  121   
  122               boolean foundEndpoint = false;
  123               for (Endpoint endpoint : endpoints) {
  124                   if (endpoint.isActive(synMessageContext)) {
  125                       foundEndpoint = true;
  126                       currentEndpoint = endpoint;
  127                       currentEndpoint.send(synMessageContext);
  128                       break;
  129                   }
  130               }
  131   
  132               if (!foundEndpoint) {
  133                   // there are no active child endpoints. so mark this endpoint as failed.
  134                   setActive(false, synMessageContext);
  135   
  136                   if (parentEndpoint != null) {
  137                       parentEndpoint.onChildEndpointFail(this, synMessageContext);
  138                   } else {
  139                       Object o = synMessageContext.getFaultStack().pop();
  140                       if (o != null) {
  141                           ((FaultHandler) o).handleFault(synMessageContext);
  142                       }
  143                   }
  144               }
  145           }
  146       }
  147   
  148       public String getName() {
  149           return this.name;
  150       }
  151   
  152       public void setName(String name) {
  153           this.name = name.trim();
  154       }
  155   
  156       /**
  157        * If this endpoint is in inactive state, checks if all immediate child endpoints are still
  158        * failed. If so returns false. If at least one child endpoint is in active state, sets this
  159        * endpoint's state to active and returns true.
  160        *
  161        * @param synMessageContext MessageContext of the current message. This is not used here.
  162        * @return true if active. false otherwise.
  163        */
  164       public boolean isActive(MessageContext synMessageContext) {
  165           boolean active = endpointContext.isActive();
  166           if (!active) {
  167               for (Endpoint endpoint : endpoints) {
  168                   if (endpoint.isActive(synMessageContext)) {
  169                       active = true;
  170                       endpointContext.setActive(true);
  171   
  172                       // don't break the loop though we found one active endpoint. calling isActive()
  173                       // on all child endpoints will update their active state. so this is a good
  174                       // time to do that.
  175                   }
  176               }
  177           }
  178           
  179           if (log.isDebugEnabled()) {
  180               log.debug("Endpoint  '" + name + "' is in state ' " + active + " '");
  181           }
  182   
  183           return active;
  184       }
  185   
  186       public void setActive(boolean active, MessageContext synMessageContext) {
  187           // setting a volatile boolean value is thread safe.
  188           this.endpointContext.setActive(active);
  189       }
  190   
  191       public List<Endpoint> getEndpoints() {
  192           return endpoints;
  193       }
  194   
  195       public void setEndpoints(List<Endpoint> endpoints) {
  196           this.endpoints = endpoints;
  197           if (endpoints.size() > 0) {
  198               currentEndpoint = endpoints.get(0);
  199           }
  200       }
  201   
  202       public void onChildEndpointFail(Endpoint endpoint, MessageContext synMessageContext) {
  203           send(synMessageContext);
  204       }
  205   
  206       public void setParentEndpoint(Endpoint parentEndpoint) {
  207           this.parentEndpoint = parentEndpoint;
  208       }
  209   }

Home » synapse-1.2-src » org.apache.synapse.endpoints » [javadoc | source]