![JAR search and dependency download from the Maven repository](/logo.png)
org.apache.servicemix.eip.patterns.Pipeline Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of servicemix-eip Show documentation
Show all versions of servicemix-eip Show documentation
The ServiceMix EIP component is a routing container where different routing patterns can be deployed as service unit.
The newest version!
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.servicemix.eip.patterns;
import java.net.URI;
import javax.jbi.management.DeploymentException;
import javax.jbi.messaging.ExchangeStatus;
import javax.jbi.messaging.Fault;
import javax.jbi.messaging.InOnly;
import javax.jbi.messaging.InOut;
import javax.jbi.messaging.MessageExchange;
import javax.jbi.messaging.MessagingException;
import javax.jbi.messaging.NormalizedMessage;
import javax.jbi.messaging.RobustInOnly;
import javax.wsdl.Definition;
import org.apache.servicemix.common.util.MessageUtil;
import org.apache.servicemix.eip.EIPEndpoint;
import org.apache.servicemix.eip.support.ExchangeTarget;
import org.apache.servicemix.jbi.exception.FaultException;
import org.apache.servicemix.jbi.jaxp.SourceTransformer;
/**
* The Pipeline component is a bridge between an In-Only (or Robust-In-Only) MEP and
* an In-Out MEP.
* When the Pipeline receives an In-Only MEP, it will send the input in an In-Out MEP
* to the tranformer destination and forward the response in an In-Only MEP to the target
* destination.
* In addition, this component is fully asynchronous and uses an exchange store to provide
* full HA and recovery for clustered / persistent flows.
*
* @author gnodet
* @version $Revision: 376451 $
* @org.apache.xbean.XBean element="pipeline"
*/
public class Pipeline extends EIPEndpoint {
private static final String TRANSFORMER = "Pipeline.Transformer";
private static final String CONSUMER_MEP = "Pipeline.ConsumerMEP";
/**
* The adress of the in-out endpoint acting as a transformer
*/
private ExchangeTarget transformer;
/**
* The address of the target endpoint
*/
private ExchangeTarget target;
/**
* The address of the endpoint to send faults to
*/
private ExchangeTarget faultsTarget;
/**
* When the faultsTarget is not specified,
* faults may be sent to the target endpoint
* if this flag is set to true
*/
private boolean sendFaultsToTarget;
/**
* The correlation property used by this component
*/
private String correlationConsumer;
/**
* The correlation property used by this component
*/
private String correlationTransformer;
/**
* The correlation property used by this component
*/
private String correlationTarget;
/**
* Should message properties be copied ?
*/
private boolean copyProperties = true;
/**
* Should message attachments be copied ?
*/
private boolean copyAttachments = true;
/**
* @return Returns the target.
*/
public ExchangeTarget getTarget() {
return target;
}
/**
* The address of the target endpoint
* @param target The target to set.
*/
public void setTarget(ExchangeTarget target) {
this.target = target;
}
/**
* @return the faultsTarget
*/
public ExchangeTarget getFaultsTarget() {
return faultsTarget;
}
/**
* The address of the endpoint to send faults to
* @param faultsTarget the faultsTarget to set
*/
public void setFaultsTarget(ExchangeTarget faultsTarget) {
this.faultsTarget = faultsTarget;
}
/**
* @return the sendFaultsToTarget
*/
public boolean isSendFaultsToTarget() {
return sendFaultsToTarget;
}
/**
* When the faultsTarget is not specified,
* faults may be sent to the target endpoint
* if this flag is set to true
*
* @param sendFaultsToTarget the sendFaultsToTarget to set
*/
public void setSendFaultsToTarget(boolean sendFaultsToTarget) {
this.sendFaultsToTarget = sendFaultsToTarget;
}
/**
* @return Returns the transformer.
*/
public ExchangeTarget getTransformer() {
return transformer;
}
/**
* The adress of the in-out endpoint acting as a transformer
*
* @param transformer The transformer to set.
*/
public void setTransformer(ExchangeTarget transformer) {
this.transformer = transformer;
}
public boolean isCopyProperties() {
return copyProperties;
}
/**
* Should message properties be copied ?
*
* @param copyProperties
*/
public void setCopyProperties(boolean copyProperties) {
this.copyProperties = copyProperties;
}
public boolean isCopyAttachments() {
return copyAttachments;
}
/**
* Should message attachments be copied ?
*
* @param copyAttachments
*/
public void setCopyAttachments(boolean copyAttachments) {
this.copyAttachments = copyAttachments;
}
/* (non-Javadoc)
* @see org.apache.servicemix.eip.EIPEndpoint#validate()
*/
public void validate() throws DeploymentException {
super.validate();
// Check target
if (target == null) {
throw new IllegalArgumentException("target should be set to a valid ExchangeTarget");
}
// Check transformer
if (transformer == null) {
throw new IllegalArgumentException("transformer should be set to a valid ExchangeTarget");
}
// Create correlation properties
correlationConsumer = "Pipeline.Consumer." + getService() + "." + getEndpoint();
correlationTransformer = "Pipeline.Transformer." + getService() + "." + getEndpoint();
correlationTarget = "Pipeline.Target." + getService() + "." + getEndpoint();
}
/* (non-Javadoc)
* @see org.apache.servicemix.eip.EIPEndpoint#processSync(javax.jbi.messaging.MessageExchange)
*/
protected void processSync(MessageExchange exchange) throws Exception {
if (!(exchange instanceof InOnly)
&& !(exchange instanceof RobustInOnly)) {
fail(exchange, new UnsupportedOperationException("Use an InOnly or RobustInOnly MEP"));
return;
}
// Create exchange for target
InOut tme = getExchangeFactory().createInOutExchange();
transformer.configureTarget(tme, getContext());
// Send in to listener and target
MessageUtil.transferInToIn(exchange, tme);
sendSync(tme);
// Check result
if (tme.getStatus() == ExchangeStatus.DONE) {
throw new IllegalStateException("Received a DONE status from the transformer");
// Errors must be sent back to the consumer
} else if (tme.getStatus() == ExchangeStatus.ERROR) {
fail(exchange, tme.getError());
} else if (tme.getFault() != null) {
processFault(exchange, tme);
// This should not happen
} else if (tme.getOutMessage() == null) {
throw new IllegalStateException("Exchange status is " + ExchangeStatus.ACTIVE
+ " but has no correlation set");
// This is the answer from the transformer
} else {
MessageExchange me = getExchangeFactory().createExchange(exchange.getPattern());
target.configureTarget(me, getContext());
MessageUtil.transferOutToIn(tme, me);
copyPropertiesAndAttachments(exchange.getMessage("in"), me.getMessage("in"));
sendSync(me);
done(tme);
if (me.getStatus() == ExchangeStatus.DONE) {
done(exchange);
} else if (me.getStatus() == ExchangeStatus.ERROR) {
fail(exchange, me.getError());
} else if (me.getFault() != null) {
if (exchange instanceof InOnly) {
// Do not use the fault has it may contain streams
// So just transform it to a string and send an error
String fault = new SourceTransformer().contentToString(me.getFault());
done(me);
fail(exchange, new FaultException(fault, null, null));
} else {
Fault fault = MessageUtil.copyFault(me);
MessageUtil.transferToFault(fault, exchange);
done(me);
sendSync(exchange);
}
} else {
throw new IllegalStateException("Exchange status is " + ExchangeStatus.ACTIVE
+ " but has no correlation set");
}
}
}
private void processFault(MessageExchange exchange, InOut tme) throws Exception {
// Faults must be sent to the target / faultsTarget
if (faultsTarget != null || sendFaultsToTarget) {
MessageExchange me = getExchangeFactory().createExchange(exchange.getPattern());
(faultsTarget != null ? faultsTarget : target).configureTarget(me, getContext());
MessageUtil.transferToIn(tme.getFault(), me);
copyPropertiesAndAttachments(exchange.getMessage("in"), me.getMessage("in"));
sendSync(me);
done(tme);
if (me.getStatus() == ExchangeStatus.DONE) {
done(exchange);
} else if (me.getStatus() == ExchangeStatus.ERROR) {
fail(exchange, me.getError());
} else if (me.getFault() != null) {
if (exchange instanceof InOnly) {
// Do not use the fault has it may contain streams
// So just transform it to a string and send an error
String fault = new SourceTransformer().contentToString(me.getFault());
done(me);
fail(exchange, new FaultException(fault, null, null));
} else {
Fault fault = MessageUtil.copyFault(me);
MessageUtil.transferToFault(fault, exchange);
done(me);
sendSync(exchange);
}
} else {
throw new IllegalStateException("Exchange status is " + ExchangeStatus.ACTIVE
+ " but has no correlation set");
}
// Faults must be sent back to the consumer
} else {
if (exchange instanceof InOnly) {
// Do not use the fault has it may contain streams
// So just transform it to a string and send an error
String fault = new SourceTransformer().contentToString(tme.getFault());
done(tme);
fail(exchange, new FaultException(fault, null, null));
} else {
Fault fault = MessageUtil.copyFault(tme);
MessageUtil.transferToFault(fault, exchange);
done(tme);
sendSync(exchange);
}
}
}
/* (non-Javadoc)
* @see org.apache.servicemix.eip.EIPEndpoint#processAsync(javax.jbi.messaging.MessageExchange)
*/
protected void processAsync(MessageExchange exchange) throws Exception {
// The exchange comes from the consumer
if (exchange.getRole() == MessageExchange.Role.PROVIDER) {
processAsyncProvider(exchange);
// If the exchange comes from the transformer
} else if (Boolean.TRUE.equals(exchange.getProperty(TRANSFORMER))) {
processAsyncTransformerResponse(exchange);
// The exchange comes from the target
} else {
processAsyncTargetResponse(exchange);
}
}
private void processAsyncProvider(MessageExchange exchange) throws Exception {
// A DONE status from the consumer can only be received
// when a fault has been sent
if (exchange.getStatus() == ExchangeStatus.DONE) {
String transformerId = (String) exchange.getProperty(correlationTransformer);
String targetId = (String) exchange.getProperty(correlationTarget);
if (transformerId == null && targetId == null) {
throw new IllegalStateException("Exchange status is " + ExchangeStatus.DONE
+ " but has no correlation set");
}
// Load the exchange
MessageExchange me = (MessageExchange) store.load(targetId != null ? targetId : transformerId);
done(me);
// Errors must be sent back to the target or transformer
} else if (exchange.getStatus() == ExchangeStatus.ERROR) {
String transformerId = (String) exchange.getProperty(correlationTransformer);
String targetId = (String) exchange.getProperty(correlationTarget);
if (transformerId == null && targetId == null) {
throw new IllegalStateException("Exchange status is " + ExchangeStatus.DONE
+ " but has no correlation set");
}
// Load the exchange
MessageExchange me = (MessageExchange) store.load(targetId != null ? targetId : transformerId);
fail(me, exchange.getError());
// This is a new exchange
} else if (exchange.getProperty(correlationTransformer) == null) {
if (!(exchange instanceof InOnly) && !(exchange instanceof RobustInOnly)) {
fail(exchange, new UnsupportedOperationException("Use an InOnly or RobustInOnly MEP"));
return;
}
// Create exchange for target
MessageExchange tme = getExchangeFactory().createInOutExchange();
transformer.configureTarget(tme, getContext());
// Set correlations
exchange.setProperty(correlationTransformer, tme.getExchangeId());
tme.setProperty(correlationConsumer, exchange.getExchangeId());
tme.setProperty(TRANSFORMER, Boolean.TRUE);
tme.setProperty(CONSUMER_MEP, exchange.getPattern());
// Put exchange to store
store.store(exchange.getExchangeId(), exchange);
// Send in to listener and target
MessageUtil.transferInToIn(exchange, tme);
send(tme);
} else {
throw new IllegalStateException("Exchange status is " + ExchangeStatus.ACTIVE
+ " but has no correlation set");
}
}
private void processAsyncTransformerResponse(MessageExchange exchange) throws Exception {
// Retrieve the correlation id
String consumerId = (String) exchange.getProperty(correlationConsumer);
if (consumerId == null) {
throw new IllegalStateException(correlationConsumer + " property not found");
}
// This should not happen beacause the MEP is an In-Out
// and the DONE status is always sent by the consumer (us)
if (exchange.getStatus() == ExchangeStatus.DONE) {
throw new IllegalStateException("Received a DONE status from the transformer");
// Errors must be sent back to the consumer
} else if (exchange.getStatus() == ExchangeStatus.ERROR) {
MessageExchange me = (MessageExchange) store.load(consumerId);
fail(me, exchange.getError());
} else if (exchange.getFault() != null) {
// Faults must be sent to faultsTarget / target
if (faultsTarget != null || sendFaultsToTarget) {
// Retrieve the consumer MEP
URI mep = (URI) exchange.getProperty(CONSUMER_MEP);
if (mep == null) {
throw new IllegalStateException("Exchange does not carry the consumer MEP");
}
MessageExchange me = getExchangeFactory().createExchange(mep);
(faultsTarget != null ? faultsTarget : target).configureTarget(me, getContext());
me.setProperty(correlationConsumer, consumerId);
me.setProperty(correlationTransformer, exchange.getExchangeId());
store.store(exchange.getExchangeId(), exchange);
MessageUtil.transferToIn(exchange.getFault(), me);
copyPropertiesAndAttachments(exchange.getMessage("in"), me.getMessage("in"));
send(me);
// Faults must be sent back to the consumer
} else {
MessageExchange me = (MessageExchange) store.load(consumerId);
if (me instanceof InOnly) {
// Do not use the fault has it may contain streams
// So just transform it to a string and send an error
String fault = new SourceTransformer().contentToString(exchange.getFault());
fail(me, new FaultException(fault, null, null));
done(exchange);
} else {
store.store(exchange.getExchangeId(), exchange);
MessageUtil.transferFaultToFault(exchange, me);
send(me);
}
}
// This is the answer from the transformer
} else if (exchange.getMessage("out") != null) {
// Retrieve the consumer MEP
URI mep = (URI) exchange.getProperty(CONSUMER_MEP);
if (mep == null) {
throw new IllegalStateException("Exchange does not carry the consumer MEP");
}
MessageExchange me = getExchangeFactory().createExchange(mep);
target.configureTarget(me, getContext());
me.setProperty(correlationConsumer, consumerId);
me.setProperty(correlationTransformer, exchange.getExchangeId());
store.store(exchange.getExchangeId(), exchange);
MessageUtil.transferOutToIn(exchange, me);
if (copyProperties || copyAttachments) {
MessageExchange cme = (MessageExchange) store.load(consumerId);
if (cme != null) {
NormalizedMessage cmeInMsg = cme.getMessage("in");
NormalizedMessage meInMsg = me.getMessage("in");
copyPropertiesAndAttachments(cmeInMsg, meInMsg);
store.store(consumerId, cme);
}
}
send(me);
// This should not happen
} else {
throw new IllegalStateException("Exchange status is " + ExchangeStatus.ACTIVE
+ " but has no Out nor Fault message");
}
}
private void processAsyncTargetResponse(MessageExchange exchange) throws Exception {
// Retrieve the correlation id for the consumer
String consumerId = (String) exchange.getProperty(correlationConsumer);
if (consumerId == null) {
throw new IllegalStateException(correlationConsumer + " property not found");
}
// Retrieve the correlation id for the transformer
String transformerId = (String) exchange.getProperty(correlationTransformer);
if (transformerId == null) {
throw new IllegalStateException(correlationTransformer + " property not found");
}
// This should be the last message received
if (exchange.getStatus() == ExchangeStatus.DONE) {
// Need to ack the transformer
MessageExchange tme = (MessageExchange) store.load(transformerId);
done(tme);
// Need to ack the consumer
MessageExchange cme = (MessageExchange) store.load(consumerId);
done(cme);
// Errors should be sent back to the consumer
} else if (exchange.getStatus() == ExchangeStatus.ERROR) {
// Need to ack the transformer
MessageExchange tme = (MessageExchange) store.load(transformerId);
done(tme);
// Send error to consumer
MessageExchange cme = (MessageExchange) store.load(consumerId);
fail(cme, exchange.getError());
// If we have a robust-in-only MEP, we can receive a fault
} else if (exchange.getFault() != null) {
// Need to ack the transformer
MessageExchange tme = (MessageExchange) store.load(transformerId);
done(tme);
// Send fault back to consumer
store.store(exchange.getExchangeId(), exchange);
MessageExchange cme = (MessageExchange) store.load(consumerId);
cme.setProperty(correlationTarget, exchange.getExchangeId());
MessageUtil.transferFaultToFault(exchange, cme);
send(cme);
// This should not happen
} else {
throw new IllegalStateException("Exchange from target has a " + ExchangeStatus.ACTIVE
+ " status but has no Fault message");
}
}
protected Definition getDefinitionFromWsdlExchangeTarget() {
Definition rc = super.getDefinitionFromWsdlExchangeTarget();
if (rc != null) {
// TODO: This components wsdl is == transformer wsdl without the out message.
// need to massage the result wsdl so that it described an in only exchange
}
return rc;
}
/**
* Copies properties and attachments from one message to another
* depending on the endpoint configuration
*
* @param from the message containing the properties and attachments
* @param to the destination message where the properties and attachments are set
*/
private void copyPropertiesAndAttachments(NormalizedMessage from, NormalizedMessage to) throws MessagingException {
if (copyProperties) {
copyProperties(from, to);
}
if (copyAttachments) {
copyAttachments(from, to);
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy