Mostrando entradas con la etiqueta fsw. Mostrar todas las entradas
Mostrando entradas con la etiqueta fsw. Mostrar todas las entradas

lunes, 1 de junio de 2015

...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.

jueves, 12 de febrero de 2015

...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.

jueves, 6 de noviembre de 2014

...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

viernes, 24 de octubre de 2014

...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)