…use Infinispan caches with SwitchYard

Sometimes, when developing SwitchYard services you might need to develop certain functionality where a cache could probably provide you with great benefit, things like:
  • Clustered configuration
  • Clustered storage of information
  • Clustered synchronization service
We are lucky that we can use Infinispan cache with SwitchYard, as it is in the application server, and if you are using FSW you are entitled to use it for your applications, and you do not need an additional entitlement for JDG.
Here, I’m going to explain very briefly what are the parts you need to take into ocnsideration in order to make use of Infinispan. The rest, what to do with the cache, then falls down on your side.

Configuration

Wildfly and EAP brings into their configuration the infinispan subsystem, where you can define you own cache containers. A cache container is a logical grouping of caches, that will be registered and accesible through JNDI for your application to use. There are multiple configuration that you can set per container, and per cache in a container, and you should check Infinispan configuration for all the available options, but the section you can/should configure is like this:
<subsystem xmlns="urn:jboss:domain:infinispan:1.4">
....
<cache-container name="switchyard" default-cache="default" start="EAGER">
<transport lock-timeout="60000"/>
<replicated-cache name="default" mode="SYNC" start="EAGER" batching="true">
<locking isolation="REPEATABLE_READ"/>
</replicated-cache>
</cache-container>
<cache-container name="mycustomcache" default-cache="cacheA" start="EAGER">
<transport lock-timeout="60000"/>
<distributed-cache name="cacheA" l1-lifespan="1000" mode="ASYNC" batching="true">
<eviction strategy="LRU" max-entries="1000"/>
</distributed-cache>
<distributed-cache name="cacheB" l1-lifespan="0" mode="ASYNC" batching="true">
<eviction strategy="LRU" max-entries="10000"/>
<file-store/>
</distributed-cache>
</cache-container>
</subsystem>
Keep in mind, that you will be required to start the server with a -ha profile to have replication and jgroups started, otherwise you will only have local caches.

Usage

The first thing you need to do in your application is to inject the CacheContainer. As the CacheContainer is registered in JNDI, it can easily be injected as a Resource in the java:jboss/infinispan/container/CACHE_CONTAINER name.
@Resource(lookup = "java:jboss/infinispan/container/switchyard")
private CacheContainer container;
Once you have the cache container, you need the concrete cache for your use. In the example configuration above, there are 2 caches defined (cacheA, cacheB). You can get a reference to the cache through the CacheManager. This can be done once, if you set your component as ApplicationScoped, or every time, or using a Singleton, or any other pattern.
private Cache<String, String> cache;
...
this.cache = this.container.getCache();
And now you can use your cache to store/retrieve information.
cache.put(KEY, value);
cache.putIfAbsent(KEY, value, 10L, TimeUnit.SECONDS);
cache.get(KEY);
cache.remove(KEY);
....
Check out the complete Infinispan documentation or the API.
Remember to check the version of Infinispan for the application server you are using. If FSW, this is 5.2.7.Final.
Check out some sample application.

…using jolokia to monitor/manage SwitchYard

Install jolokia

Get the latest jolokia war file from their website, rename it to jolokia.war and deploy it into the server.

Get a list of all SwitchYard MBeans

All SwitchYard MBeans are registered under the org.switchyard.admin JMX domain name, as per thedocumentation. So we can get a list of what we have:
http://localhost:8080/jolokia/list/org.switchyard.admin
or a description of an MBean:
http://localhost:8080/jolokia/list/org.switchyard.admin/name=%22_OrderService_soap_1%22,service=%22%7Burn:switchyard-quickstart:bean-service:0.1.0%7DOrderService%22,type=Binding

As it is mentioned on the documentation, there are different types of MBeans:
  • Application: Management interface for a SwitchYard application.
  • Service: Management interface for a composite service in a SwitchYard application. One MBean is registered per composite service.
  • Reference: Management interface for a composite reference in a SwitchYard application. One MBean is registered per composite reference.
  • Binding: Management interface for a gateway binding attached to a composite service or reference. One MBean is registered per binding instance on an application’s composite services and references.
  • ComponentService: Management interface for a component service in a SwitchYard application. One MBean is registered per component service.
  • ComponentReference: Management interface for a component reference in a SwitchYard application. One MBean is registered per component reference.
  • Transformer: Management interface for a transformer in a SwitchYard application. One MBean is registered per transformer.
  • Validator: Management interface for a validator in a SwitchYard application. One MBean is registered per validator.
  • Throttling: Management interface for throttling a service in a SwitchYard application. One ThrottlingMBean is registered per composite service instance.
There are two additional MBean objects, that are superclasses, that define custom behavior.
  • Lifecycle: Supertype of BindingMXBean which provides operations related to lifecycle control for service and reference bindings.
  • Metris: Supertype of multiple MBeans providing message metrics information.

Starting/Stopping bindings

As service and reference bindings extends the Lifecycle MXBean, we can start or stop a binding, and know in what state they are:
  • Check the state
http://localhost:8080/jolokia/read/org.switchyard.admin:name=%22_OrderService_soap_1%22,service=%22%7Burn:switchyard-quickstart:bean-service:0.1.0%7DOrderService%22,type=Binding/State
  • Stop the binding
http://localhost:8080/jolokia/exec/org.switchyard.admin:name=%22_OrderService_soap_1%22,service=%22%7Burn:switchyard-quickstart:bean-service:0.1.0%7DOrderService%22,type=Binding/start
  • Check the state
http://localhost:8080/jolokia/read/org.switchyard.admin:name=%22_OrderService_soap_1%22,service=%22%7Burn:switchyard-quickstart:bean-service:0.1.0%7DOrderService%22,type=Binding/State
  • Start the binding
http://localhost:8080/jolokia/exec/org.switchyard.admin:name=%22_OrderService_soap_1%22,service=%22%7Burn:switchyard-quickstart:bean-service:0.1.0%7DOrderService%22,type=Binding/start
  • Check the state
http://localhost:8080/jolokia/read/org.switchyard.admin:name=%22_OrderService_soap_1%22,service=%22%7Burn:switchyard-quickstart:bean-service:0.1.0%7DOrderService%22,type=Binding/State

Geting metrics

If you want to get metrics, it is very simple, the only thing is that you need to know which metrics are worth for you, as every component, composite and binding provides with many metrics. Once you know what information you need, you can use jolokia to get the information, and maybe use that information to feed an ElasticSearch or InfluxDB database, and use Kibana/Graphana to view the information in a graphical way, and explore this information. Also RTGov is available.
  • Get all the information available for a binding
http://localhost:8080/jolokia/read/org.switchyard.admin:name=%22_OrderService_soap_1%22,service=%22%7Burn:switchyard-quickstart:bean-service:0.1.0%7DOrderService%22,type=Binding
  • Get the TotalCount for a binding
http://localhost:8080/jolokia/read/org.switchyard.admin:name=%22_OrderService_soap_1%22,service=%22%7Burn:switchyard-quickstart:bean-service:0.1.0%7DOrderService%22,type=Binding/TotalCount

Getting metrics from multiple MBeans

You might want to get some metrics for more than one MBean. You can use wildcards for this, and knowing which types of MBeans and information you want is very easy.
http://localhost:8080/jolokia/read/org.switchyard.admin:name=*,service=*,type=Binding/MinProcessingTime
  • More complex pattern
http://localhost:8080/jolokia/read/org.switchyard.admin:name=%22*soap*%22,service=*,type=Binding/MinProcessingTime

Search the MBeans you care for

When you have many apps deployed, you might not know which MBeans are there, and their ObjectNames. You can search for them:
http://localhost:8080/jolokia/search/org.switchyard.admin:type=Binding,*

Demo

If you want to test this, I have created a Dockerfile that you can use right away, based on the latest SwitchYard image. It is available here.
You just need to get this file, and build the image:
curl https://raw.githubusercontent.com/jorgemoralespou/fsw-demo/master/monitoring-with-jolokia/Dockerfile -o Dockerfile
docker build --rm -t "switchyard-with-jolokia"
And then run it:
docker run -it --rm -p 8080:8080 -p 9990:9990 switchyard-with-jolokia

…where to bundle SwitchYard application’s dependencies

The one problem, though, that I’ve constantly see is where to package your dependencies. We constantly fail to get the common classes used by many of the applications in a proper place.

Package common classes and model classes

If a class is going to be used by 2 or more SwitchYard applications, this class needs to be placed in a place where both applications will load it using the same classloader.
In a JEE world if the same class is loaded with different classloaders, it is not the same class.
Let’s take for example an application consisting of 3 SwitchYard applications, 2 of them (Sy app 1 and Sy app 2) packaged in an .ear file and another one (Sy app 3) packaged as a jar. These applications use some common classes (JAXB model, Entity beans, utilities, BaseMessageComposers, …​) that are packaged in two jar files, dependency A and dependency B.
If you have a request that initiated through Sy app 1 and calls to Sy app 2, you can safely use any class that is bundled in dependencyA or dependencyB, as long as for dependencyB you have a reference to the appropriate module (This dependency can be deployed either as a dynamic module, if left in the deployments folder, or as a static module, if registered as a module in modules folder). A reference to a module can be specified in the META-INF/MANIFEST file or in jboss-deployment-structure.xml file. (See JBoss documentation for how to do this).
If you have a requets that initiated through Sy app 1 and calls to Sy app 2, you can only use classes that are bundled in dependencyB for request object, otherwise you’ll most probably have a ClassCastException due to the class being loaded with two different class loaders. Any other use of classes from dependency A or B should be safe as long as it doesn’t use any object that is going from Sy app1 to Sy app 2, or viceversa, on the response path.
There are also some bugs in SY 1.1.1 (FSW 6.0) that raises some other similar and related problems, due to classloaders not properly propagated, and the incorrect use of some static code in serialization framework.

…proxying a SOAP service with 3 faults in SwitchYard

This document describes a problem that I’ve faced with SwitchYard due to one of it’s known issues/features/limitations.

Problem

I needed to create a proxy service for a SOAP Web Service where I had a contract with 3 faults.
public interface CustomerListServicePortType {
public CustomerListResponse getCustomerList(CustomerListRequest parameters) throws
GeneralError, CustomerNotFound, InvalidUserCredentials;
}
SwitchYard has one limitation, it only accepts contracts with one Exception type (as well as only accepts one single input type). When I created the initial service for this, and deployed my service, I had SwitchYard telling me about this:
org.switchyard.SwitchYardException: SWITCHYARD010005: Service operations on a Java interface can only throw one type of exception.
One option could be to modify the contract, but as this is to proxy a legacy service, I need to maintain my contract, so I looked into various options, out of which I’ll describe the one that was the easiest for me.

Solution

I created an internal Contract, for my service, to only have one single Exception:
public interface CustomerListServicePortType {
public CustomerListResponse getCustomerList(CustomerListRequest parameters) throws
CustomerListException;
}
Use transformers to map from and to the original exceptions to my new “unique” exception. As when doing SOAPFault handling, what really gets marshalled/unmarshalled is the FaultInfo, I decided to keep the original FaultInfo in my new Exception:
import org.w3c.dom.Element;

public class CustomerListException extends Exception {

private Element faultInfo;

public CustomerListException(Element cause) {
faultInfo = cause;
}

public Element getFaultInfo() {
return faultInfo;
}
}
And my tranformers where so simple, that I was happy not having to deal with DOM parsing and Element, and all that stuff.
public final class ExceptionTransformers {

@Transformer(from = "{http://common/errorcodes}invalidUserCredentials")
public CustomerListException InvalidUserCredentialsToCustomerListEx(Element from) {
CustomerListException fe = new CustomerListException(from);
return fe;
}

@Transformer(from = "{http://common/errorcodes}generalError")
public CustomerListException transformGeneralErrorToCustomerListEx(Element from) {
CustomerListException fe = new CustomerListException(from);
return fe;
}

@Transformer(from = "{http://common/errorcodes}customerNotFound")
public CustomerListException transformCustomerNotFoundToCustomerListEx(Element from) {
CustomerListException fe = new CustomerListException(from);
return fe;
}

@Transformer(to = "{http://common/errorcodes}customerNotFound")
public Element transformCustomerListExToCustomerNotFound(CustomerListException e){
return e.getFaultInfo();
}

@Transformer(to = "{http://common/errorcodes}generalError")
public Element transformCustomerListExToGeneralError(CustomerListException e){
return e.getFaultInfo();
}

@Transformer(to = "{http://common/errorcodes}invalidUserCredentials")
public Element transformCustomerListExToInvalidUserCredentials(CustomerListException e){
return e.getFaultInfo();
}
}
These transformers gets registered as Java transformers (due to the @Transform annotation).
And everything works like a charm

…make JBDS faster for SwitchYard

While working with SwitchYard, JBoss Developer Studio can be a pain in the ass. Red Hat is working to provide some better user experience, but in the meantime, you can try some of these tips.

Increase heap memory

Eclipse needs a lot of memory, and maven and SwitchYard projects even more, so provide with a good amount of it to your eclipse. Modify jbdevstudio.ini in the appropiate section:
-vmargs
-XX:MaxPermSize=256m
-Xms2G
-Xmx2G
-XX:-UseParallelGC
-XX:+AggressiveOpts
-XX:-UseConcMarkSweepGC
Provide a good amount of memory, so if you can give 3 or 4 GBs instead of 2 better.

Disable automatic updates

Faster startup time. You’ll update or check for updates whenever you want.
Preferences --> Automatic updates --> (Disable) Automatically find new updates and notify me

Disable auto build

If you build whenever you want, the project you want, then disable. If you have a big ammount of projects you can skip having eclipse doing background building all the time. If you have few projects, you can keep it.
Project --> Build automatically (Uncheck)

Refresh workspace on startup

If you don’t do things on command line, then your workspace should be refreshed. If you use git (command line) or maven (command line) maybe you want to keep it:
General -> Startup and shutdown -> Refresh workspace on startup (Enable)

Disable validations

If you there is a lot of background task processing gone on validating your project (due to any facet your project has, like JPA, …​)
Validation -> Suspend all validations (check)

Disable startup features not needed (FUSE, …​)

Use the fewer plugins needed for your work.
General -> Startup & shutdown ->  Plugins activated on Startup (Remove FUSE, Fabric8, JBoss Central, Forge UI, JBoss Tools reporting, Equinox autoupdate)

Disable XML Honour schemas

There is a known bug in JBDS and SwitchYard, so avoid it with:
XML -> XML Files -> Validation -> Honour all XML schema locations (uncheck)

Close JPA and EAR projects if not working on them

Every project that you have opened is both, eating resources and having to be check with the background tasks, so close them if not needed (as dependencies or at all)

… using vaulted properties in SwitchYard

Description

Usually we define externalize configuration in properties files to just make the application configuration independent. But one problem we face is that this information is usually endpoints and login credentials, like username and password. For this first type of information, there is usually no need to have them encrypted, but there typically is a requirement for this when storing credentials information.
I’m going to explain how to do this in SwitchYard.
Thanks to Nacim Boukhedimi for this post
The steps to be able to use vaulted configuration is:
  • Create a vault file and store the property there
  • Configure the application to read

Create a vault file

Vault mechanism is the mechanism provided by JBoss EAP 6 to enable you to encrypt sensitive strings and store them in an encrypted keystore. This mechanism relies upon tools that are included in all supported Java Development Kit (JDK) implementations. Below is a step by step description of how to encrypt your properties stored in an external properties file.
  1. Create a directory to hold your keystore and other important information. (for instance ${jboss.server.config.dir})
  2. Enter the following command to create a keystore file named vault.keystore:
    keytool -genkey -alias vault -keyalg RSA -keysize 1024 -keystore vault.keystore
  3. Mask the Keystore Password and Initialize the Password Vault. From EAP_HOME/bin folder, run vault.sh and start a new interactive session
    The salt value, together with the iteration count (below), are used to create the hash value.
    Make a note of generated vault Configuration in a secure location. It will be used in the next step to configure EAP to use vault.
  4. Configure JBoss EAP 6 to Use the Password Vault. Copy and paste the generated vault Configuration in EAP config file:
    <vault>
    <vault-option name="KEYSTORE_URL" value="${jboss.server.config.dir}/vault.keystore"/>
    <vault-option name="KEYSTORE_PASSWORD" value="MASK-18JTA2ZfD4eISrndbFgJRk"/>
    <vault-option name="KEYSTORE_ALIAS" value="vault"/>
    <vault-option name="SALT" value="8675309K"/>
    <vault-option name="ITERATION_COUNT" value="50"/>
    <vault-option name="ENC_FILE_DIR" value="${jboss.server.config.dir}/vault/"/>
    </vault><management>

Store your data in the vault

  1. Store encrypted Sensitive strings in the Java Keystore:
    1. run vault.sh and start a new interactive session
    2. Enter the path to the keystore, the keystore password, vault name, salt, and iteration count to perform a handshake.
    3. Select the option 0 to store a value.
    4. Enter the value, vault block, and attribute name.
    5. As a result, the value is stored and a message is displayed showing the vault block, attribute name, shared key, and advice about using the string in your configuration.
      Vault Block:container
      Attribute Name:file.name
      Configuration should be done as follows:
      VAULT::container::file.name::1
      Please make note of the vaultID to use in your properties file

Use the encrypted property in your properties file

Now it is time to use the property. As we want the property to be externalized, we will define the property in a properties file, and then instruct the server to use that properties file.
  1. In your properties, refer to this property as:
 file.name=${VAULT::container::file.name::1}
You need to start the server with the P option to provide the path to the properties file.
./standalone.sh  -P=file:<path_to_properties>

Use the property in your switchyard.xml

You can refer then to this property from your switchyard.xml
      <file:binding.file>
<file:directory>/tmp/input</file:directory>
<file:fileName>${file.name}</file:fileName>
<file:consume>
<file:initialDelay>10</file:initialDelay>
<file:delay>10</file:delay>
<file:delete>true</file:delete>
</file:consume>
</file:binding.file>
The file endpoint will be scanning for files under /tmp/input/<your secret filename>

…how to read a file programmatically in SwitchYard

I’ve been asked recently how to read a file programmatically, based on a cron, or when a request is made via a call to a Service. I didn’t have an answer, well, really I had an answer and I was wrong. Today, somebody brought the topic back, and I revisited the problem, and now I have an answer, one that works, so a good answer.

Problem description

I have the following use case:
A file should be downloaded by FTP from a remote server. The download of the file can be triggered in two ways:
  • by a scheduler whose polling interval may be changed at runtime
  • by a HTTP GET Request on a specified url. The response of the HTTP call must include transformed data based on the downloaded file.
What is a good way to achieve these requirements with SY/Camel? I would like to use the bindings provided by Camel, but have no idea how they can be triggered (e.g. the FTP binding) from outside the binding.

Solution

I have created a sample project, just to demonstrate how it works, not the full problem is solved. You have to use thecontent ennricher EIP.
We have a service, with a scheduled binding (Every 30 secs) that calls a Camel component. In this component, we use pollEnrich to read a file, and the use the contents of the file (the Message) to write into a File (a Reference with file binding).
This is the route we will be using. Note the pollEnrich to read the file.
public void configure() {
from("switchyard://ProgramaticReload")
.log("Going to read the file")
.pollEnrich("file:///input?fileName=in.txt",1000)
.log("Read from file : ${body}")
.to("switchyard://FileWriterService");
}
The project is available in github

…SwitchYard in docker

Introduction

Now that there is an official docker image for SwitchYard, I’m going to explain some usages of this image to make you productive with docker and SwitchYard. This way, you’ll be able to have reproducible environments for:
  • development
  • demos
  • support/bug hunting
  • integration / testing
Let’s get us started:

SwitchYard docker official image

The official images, are maintained by Red Hat, and are published to the docker hub. You can browse the source code for the images. Currently there is only support for SwitchYard on Wildfly. Of course, on the official Wildfly image, also supported by Red Hat.
All of the JBoss community projects that have a docker image, are published in the official docker community site. From there, you can link to the individual projects. As I’m going to talk about SwitchYard, let’s see what’s there:

Get started

In order to get you started you just need to download the image
docker pull jboss/switchyard-wildfly
and create a container
docker run -it jboss/switchyard-wildfly
or in domain mode
docker run -it jboss/switchyard-wildfly /opt/jboss/wildfly/bin/domain.sh -b 0.0.0.0 -bmanagement 0.0.0.0
You’ll see that the base SwitchYard docker container is not so useful (doesn’t have an admin user), so the best thing to do, is to extend it.

Extending the SwitchYard container

First thing you need to know is what you want the container for, so let’s see some sample uses:

Development

In this use case, what you want is a container where to deploy your applications, those that you are developing, so it can be useful to have:
  • An admin user created
  • Debug port exposed
  • Binding to all interfaces, so you can access without forwarding (if required)
  • Some volumes to access your information in the container
  • Some volumes (to test file services)
Let’s create a container for this:
Dockerfile
FROM jboss/switchyard-wildfly

#
# Add admin user
RUN $JBOSS_HOME/bin/add-user.sh admin admin123! --silent

#
# Enable port for debugging with --debug
EXPOSE 8787

#
# Volumes
VOLUME /input
VOLUME /output

# Enable binding to all network interfaces and debugging inside the server
RUN echo "JAVA_OPTS="$JAVA_OPTS -Djboss.bind.address=0.0.0.0 -Djboss.bind.address.management=0.0.0.0"" >> $JBOSS_HOME/bin/standalone.conf

ENTRYPOINT ["/opt/jboss/wildfly/bin/standalone.sh"]
CMD []
I’m going to explain each and every command:
  1. FROM jboss/switchyard-wildfly, this is the base image, so we are reusing everything in there (jboss user, EAP_HOME set, and more. See doc for reference)
  2. RUN $JBOSS_HOME/bin/add-user.sh admin admin123! –silent, this creates and admin user with admin123! as password.
  3. EXPOSE 8787 adds debug port exposure (8787 is the default one in wildfly.
  4. VOLUME /inputVOLUME /output adds two volumes to the image, so we can easily acces or export this volumes if needed. They are very handy when developing file services, as we will see when we run the container.
  5. RUN echo “JAVA_OPTS=”$JAVA_OPTS -Djboss.bind.address=0.0.0.0 -Djboss.bind.address.management=0.0.0.0″” >> $JBOSS_HOME/bin/standalone.conf this adds default binding to any interface (by default only 127.0.0.1) so we can access the server via the ip or name.
  6. ENTRYPOINT [“/opt/jboss/wildfly/bin/standalone.sh”] defines default command to be executed. I like to set the command here as this image will be single purpose, so no need to be able to switch (although it is possible with –entrypoint on command line).
  7. CMD [] this is the arguments to the entrypoint, none by default, but it allows you to set on command line things like “–debug” to enable debugging mode in the container.
Now it is time to build the image:
docker build -t "jmorales/switchyard-dev" .
You can name the image as you like, as this image will be yours. Just need to think that has to have meaningul name so it is easy to remember when used.
Let’s now go to run the image:
docker run -it jmorales/switchyard-dev
This is the simplest command to run the container, but we are not using many of the power we have provided to it, so, let’s make a better command:
docker run -it -name "switchyard" -p 8080:8080 -p 9990:9990 jmorales/switchyard-dev
Now we can access the console with the admin/admin123! user that we have created.
Still not there yet. We need to be able to use file services (remember that in the container the directories will be /input and /output) and we want to debug in the container from the JBDS.
docker run -it -name "switchyard" -v /tmp/input:/input -v /tmp/output:/output -p 8080:8080 -p 9990:9990 -p 8787:8787 jmorales/switchyard-dev --debug
And even maybe use a different profile
docker run -it -name "switchyard" -v /tmp/input:/input -v /tmp/output:/output -p 8080:8080 -p 9990:9990 -p 8787:8787 jmorales/switchyard-dev --debug -c standalone-full.xml
Important things to note here:
  • The image is run in foreground, so we will be viewing the console log. Control-c will stop the container. Since we have the container created, if we want to execute it again, it is just a:
docker start switchyard
  • If you want a disposable container, you can add –rm option to the command line, and every time you stop the container it will be removed. (This option is more useful on other use cases).
  • If you always work with some options, you can just add them to your Dockerfile and create your image with these options, so no need to type them when creating the container (like the profile, –debug, ..)
Of course, this line is very long, and difficult to remember, so we can create a simple alias:
alias docker_switchyard_create="docker run -it -name "switchyard" -v /tmp/input:/input -v /tmp/output:/output -p 8080:8080 -p 9990:9990 -p 8787:8787 jmorales/switchyard-dev --debug -c standalone-full.xml"
alias docker_switchyard_start="docker start switchyard"
Once you are done, you can just delete this container. If you want a fresh instance, or just not working on it anymore:
docker rm -vf switchyard
It is important to delete the volumes if the container has volumes (with the -v) as otherwise this volumes will remain in your docker internal filesystem.

Demos

The demo use case is somehow different as you’ll probably have some application developed that you want to have in acontainer ready to start, so the container for demos will be an extension of the previous one, adding the application/configruation that you want.
FROM jboss/switchyard-wildfly

#
# Add admin user
RUN $JBOSS_HOME/bin/add-user.sh admin admin123! --silent

#
# Volumes
VOLUME /input
VOLUME /output

# Enable binding to all network interfaces and debugging inside the server
RUN echo "JAVA_OPTS="$JAVA_OPTS -Djboss.bind.address=0.0.0.0 -Djboss.bind.address.management=0.0.0.0"" >> ${JBOSS_HOME}/bin/standalone.conf

ADD myapp.war $JBOSS_HOME/standalone/deployments/
ADD standalone.xml $JBOSS_HOME/standalone/configuration/

ENTRYPOINT ["/opt/jboss/wildfly/bin/standalone.sh"]
CMD []
This example above has 3 main differences with the development one:
  • It removes the exposure of the debug port (not really neccesary)
  • It adds an application to the deployments dir ADD myapp.war $JBOSS_HOME/standalone/deployments/. This app has to be on the same directory as the Dockerfile
  • It adds some configuration to the server ADD standalone.xml $JBOSS_HOME/standalone/configuration/There are many ways to customize the configuration of your wildfly/EAP image, but this is one of the simplest.
And of course, if you had your image from the development use case created, you can just simply extend it.
FROM jmorales/switchyard-dev

#
# Add customizations
ADD myapp.war $JBOSS_HOME/standalone/deployments/
ADD standalone.xml $JBOSS_HOME/standalone/configuration/
Now, time to build your image:
docker build -t "jmorales/myapp-demo" .
And to run it
docker run -it --rm -v /tmp/input:/input -v /tmp/output:/output -p 8080:8080 -p 9990:9990 jmorales/myapp-demo
This time I’ve added –rm to the command line, so when I stop the container, it gets deleted. As this is a demo with everything there, if I need to do it again, just run the container with the same run command line.

Support

The support use case is for somebody to make the environment reproducible, so if sombeody is experiencing a problem, he can create a docker container to isolate the app and the problem, and send it back to the support engineers. Also, some times, we want to test one app with different patches, so can be useful to have all the different versions of the server container as images, so we can try an app in them.
Let’s assume we have to try a feature in SwitchYard 1.1.1 and 2.0.0, and that we have an image for both containers:
  • jboss/switchyard:1.1.1
  • jboss/switchyard:2.0.0
We can just spin up both containers and test the app to see if it works
docker run -it --rm -P jboss/switchyard:1.1.1
docker run -it --rm -P jboss/switchyard:2.0.0
Once we have both containers (just note that if run in foreground, need to run in different terminals, and have different ports exported. I have added -P to auto export ports), we can go to the corresponding consoles and deploy the app and test.
If we want to have our tools set to certain ports (to be predictive) it is easier to have the ports defined in the command line, and use one container at a time

Integration / Testing

In the integration test case, what we want is to have our integration tools spinning up the container for us and deploying the app into this container, do all the integration tests and then stop/destroy the container.
This can easily be achievable with Jenkins (or many of the CI servers out there).
This way we can:
  • Have a clean environment for every test / app
  • Test against many different versions of the Application Server container in an automated way
When adopting testing agains containers, the time for detecting problems lowers so much, that the effort it makes to put it in action pays back very soon.

Tips for developers

As we can develop easily with docker as the container for our Application server, we can easily configure our tools to use this container, so we can have a maven profile to use our containers:
    <profile>
<id>sy-1</id>
<properties>
<jboss-as.hostname>localhost</jboss-as.hostname>
<jboss-as.port>9999</jboss-as.port>
<jboss-as.username>admin</jboss-as.username>
<jboss-as.password>admin123!</jboss-as.password>
</properties>
</profile>
<profile>
<id>sy-2</id>
<properties>
<jboss-as.hostname>localhost</jboss-as.hostname>
<jboss-as.port>19999</jboss-as.port>
<jboss-as.username>admin</jboss-as.username>
<jboss-as.password>admin123!</jboss-as.password>
</properties>
</profile>
And we can do a
mvn clean install jboss-as:deploy -P sy-1
to deploy to the SwitchYard 1 container (with port 9999 exported at localhost 9999), or
mvn clean install jboss-as:deploy -P sy-2
to deploy to the SwitchYard 2 container (with port 9999 exported at localhost 19999).

…SwitchYard contracts

Description

When working with SwitchYard we have to define the contraccts for our services as well as for our component implementations. In order to define our contracts there is different ways, and different points, depending on:
  • Component implementation
  • Service binding
As we can see in the picture above, in a simple service we can find, at least, the following contracts:
  • Component contracts
    • Component service
    • Component reference
  • Composite contracts
    • Composite service
    • Composite reference
  • Binding contracts
    • Service Binding
    • Reference Binding
SERVICES CONTRACTS SHOULD BE CORRECTLY TYPED

Component contracts

This is the contract a component exposes or uses, depending on whether it is a service or reference contract. A component contract can be defined in 3 different ways in SwitchYard:
  • Java. Using a Java interface.
  • WSDL. Using a port type in a wsdl file.
  • ESB. Using a virtual interface definition. (No real file will be used).
A component contract in SwitchYard has the following characteristics:
  • 0..1 argument. If used, this will be the message content. It is optional as there can be operations that don’t expect a message (REST GET, Scheduled operations,…​). Used in Exchanges of type IN_ONLY and IN_OUT.
  • 0..1 return type. If used, this will be the message content for the response. Used only in Exchanges of type IN_OUT.
  • 0..1 exceptions. If used, this will be the message content for the response if there is an Exception. Used in Exchanges of type IN_ONLY and IN_OUT.
Contracts in Camel can be defined with empty parameters, and you will still be able to work with the message contant. DO NOT RELY ON THIS

Java contract

A Java contract is defined by a Java Interface.

Java components require Java contracts.

WSDL contract

A WSDL contract is defined by a port type in a wsdl file.

ESB contract

An ESB contract is a virtual contract (no file required) that declares the types of the input, output and exception types.

This contract can only be used in components with one single operation.

Transformations between contracts

When a message flows in SwitchYard, and there is different types in the contracts on both ends of the “channel”, a transformation must be done. There can be implicit or explicit transformations happening, depending on where they have to happen, and there are extension points to define how the transformation between types in contracts must happen.

Composite Service Binding and Composite Service / Composite Reference and Composite Reference Binding

Contract differences are handled in the ServiceHandlers when composing and decomposing the SwitchYard message.
Any difference in contracts must be handled in the Message composer.
Camel and Http MessageComposers will do Camel Implicit Transformations if required. If target type is JAXB, the class needs to have @XMLRootElement annotation.

Composite Service and Component Service / Component Reference and Composite Reference

Contract differences are handled by transformers defined in the composite application, which are applied by theExchangeHandler chain during the execution of the Exchange.
The transformers usually map from an origin type to a destination type.
When the Exchange is between a composite service and a component service:
  • In the IN phase, from is the argument’s type of the composite service and the to is the type in the component service.
  • In the OUT phase, from is the return/exception type of the component service and the to is the return/exception typein the composite service.
When the Exchange is between a component reference and a composite reference:
  • In the IN phase, from is the argument’s type of the component reference and the to is the type in the composite reference.
  • In the OUT phase, from is the return/exception type of the composite reference and the to is the return/exception typein the component reference.
There will be some implicit transformation happening (not need to declare a transformer) if SwitchYard supports automatic transformation between both types, as declared by CamelTransformer
As of SY 1.1.1, there is no implicit transformation for primitives types

Component Service and Component Reference

Contract differences are handled in the component implementation, and has to be explicitly transformed.

Special attention

  • If a Composite Service does not declare an interface, it will use the interface defined by the promoted Component Service
  • Every Component can have one Service
  • Binding name can be null. In this case, a binding name will be automatically generated with “ServiceName+BindingType+i”
  • When the input parameter of a service contract is empty, the message will not be change, it will be in it’s original form (e.g. java.io.Reader for streaming bindings like HTTP, File,…​)