O documento descreve como usar o Spring Application para criar fluxos dinâmicos em Mulesoft de acordo com uma configuração variável. Ele propõe criar um fluxo modelo parametrizado e, em seguida, programáticamente criar contextos de aplicação individuais para cada configuração, em vez de adicionar fluxos duplicados em tempo de compilação. Um exemplo mostra como ler propriedades de configuração para criar múltiplos contextos de aplicação com fluxos personalizados para cada parceiro.
1. Fluxo dinâmicos usando Spring Aplication
A capacidade de controlar a forma como mula cria e gerencia contexto de aplicação
Primavera é um recurso muito útil. Em um compromisso com o cliente recente, eu tinha que
realizar uma operação de integração idêntico, mas a partir de um número variável de fontes
(diferentes para cada ambiente).
Em mula, isto pode ser realizado por:
Adicionando fluxos específicos do sistema duplicado em tempo de compilação, ou
Criando um fluxo modelo, parametrização de configuração e criar uma instância contexto de
aplicação para cada configuração.
Eu prefiro a opção 2, uma vez que é seco e permite controlar facilmente o número de fluxos
de configuração não código.
Como um caso de uso, vamos supor que temos parceiros de negócios que colocam arquivos
em baldes S3, onde buscá-las e movê-los para um local S3 separado. Vamos agora dizer que
nós temos um número variável de parceiros e, portanto, um número variável de origem
baldes S3.
On-boarding novos parceiros significaria que origem e de destino baldes seria diferente e,
provavelmente, frequência de consulta tão bem, mas resto deve permanecer o mesmo. Isto
pode ser alcançado através de:
a adição de um parceiro de configuração específica, e, em seguida
programaticamente criando um contexto de aplicação de um fluxo de template
Construir o nosso aplicativo
Um fluxo modelo é necessário para que possamos parametrizar-lo e mudar endpoints.
Vamos usar seguinte pasta de destino de fluxo e fonte de mudança / baldes de destino e
frequência de consulta.
<flow>
<poll doc:name="Poll">
2. <fixed-frequency-scheduler frequency="20" timeUnit="SECONDS"/>
<logger message="Flow Start: " level="INFO" doc:name="Log Start"/>
</poll>
<s3:list-objects config-ref="Amazon_S3_GlobalConnector" bucketName="test-partner-1" d
oc:name="List objects"/>
<foreach collection="#[payload]" doc:name="For Each">
<enricher doc:name="Message Enricher" target="#[flowVars['copyObjectResult']]">
<s3:copy-object config-ref="Amazon_S3_GlobalConnector" destinationBucketName="tes
t-system-1" destinationKey="#[payload.getKey()]" sourceBucketName="#[payload.getBuck
etName()]" sourceKey="#[payload.getKey()]" doc:name="Copy object"/>
</enricher>
<s3:delete-object config-ref="Amazon_S3_GlobalConnector" bucketName="test-partner-1
" key="#[payload.getKey()]" doc:name="Delete object"/>
</foreach>
<logger message="Flow End" level="INFO" doc:name="Log Start"/>
</flow>
Bater em mula fases do ciclo de vida de aplicação nos daria a oppurtunity para ler um
arquivo de propriedades e começar um contexto de aplicação com os detalhes específicos de
parceiros. Uma classe Java que implementa org.mule.api.lifecycle.Initialisable e
org.mule.api.lifecycle.Disposable nos deixaria fazer isso.
Durante a fase de Inicializar, mudamos parceiro específico detalhes em nosso fluxo de
modelo e iniciar um contexto de aplicação.
Em fase de descarte, paramos e dispor nosso contexto (s) pedido
public void initialise() throws InitialisationException {
// read template flow
// replace endpoints with properties from configuration file
// create and start an application context
}
public void dispose() {
// stop and dispose application context(s)
3. }
E, finalmente, uma falha principal, que nos dá acesso às propriedades do arquivo, e chutar
iniciar nossa aplicação.
<context:property-placeholder location="mule-app.properties" />
<flow>
<component doc:name="RouteFactory">
<singleton-object class="demo.RouteFactory">
<property key="partnerCount" value="${partner-count}"/>
</singleton-object>
</component>
</flow>
Dependendo do número de parâmetros, arquivo de propriedades pode acabar olhar como
seguir
partner-count=2
partner-1.flow-name = partner-one-flow
partner-1.polling-frequency = 10
partner-1.source-bucket = test-partner-1
partner-1.destination-folder = partner1/
partner-1.destination-bucket = test-system-1
partner-2.flow-name = partner-two-flow
partner-2.polling-frequency = 20
partner-2.source-bucket = test-partner-2
partner-2.destination-folder =
partner-2.destination-bucket = test-system-2
RouteFactory.java
6. listObject.item(0).getAttributes().getNamedItem("bucketName").setN
// change destinationBucket and destinationKey(append folder name t
copyObject.item(0).getAttributes().getNamedItem("destinationBucke
copyObject.item(0).getAttributes().getNamedItem("destinationKey")
"payload.getKey()]");
// delete an object from a specific bucket
deleteObject.item(0).getAttributes().getNamedItem("bucketName").s
config.add(getStringFromDoc(flowTemplate));
addFlow(config, flowName);
}catch(Exception e) {
e.printStackTrace(System.out);
}
}// end of while
}
@Override
public void dispose() {
System.out.println(this.getClass().getName() + ".dispose(). Total partner count : "
Iterator<String> iterator = initialisedContexts.keySet().iterator();
while ( iterator.hasNext() ) {
MuleContext muleContext = initialisedContexts.get(iterator.next());
System.out.println(this.getClass().getName() + "Stopping context with flow
try {
muleContext.stop();
muleContext.dispose();
} catch (MuleException e) {
System.out.println(this.getClass().getName() + "Cannot stop context
e.printStackTrace(System.out);
}
}
}
7. private String getStringFromDoc(Document doc) throws TransformerException {
DOMSource domSource = new DOMSource(doc);
StringWriter writer = new StringWriter();
StreamResult result = new StreamResult(writer);
TransformerFactory tf = TransformerFactory.newInstance();
Transformer transformer = tf.newTransformer();
transformer.transform(domSource, result);
writer.flush();
return writer.toString();
}
private boolean addFlow(ArrayList<String> configs, String flowName) {
boolean flag = false;
try {
// add to mule context
MuleContext muleContext = new DefaultMuleContextFactory().createMule
ConfigResource configResource[] = new ConfigResource[1];
int i = 0 ;
for (String config : configs) {
configResource[i] = new ConfigResource(flowName, new ByteArray
i++;
}
ConfigurationBuilder builder = new SpringXmlConfigurationBuilder(config
builder.configure(muleContext);
muleContext.start();
initialisedContexts.put(flowName, muleContext);
flag = true;
} catch (MuleException me) {
me.printStackTrace(System.out);
}
return flag;
}
8. public void setPartnerCount(int partnerCount) {
this.partnerCount = partnerCount;
}
}
Conclusão
O exemplo que acabamos de considerar é bastante simples. Para a ousadia entre nós,
poderíamos até mesmo experimentar com a adição de uma API HTTP que cria e destrói os
fluxos para nós sem a necessidade de reiniciar a nossa aplicação.