Microservices and Java EE

Lance Ball / @lanceball

Microservices

A software architecture style in which complex applications are composed of small, independent processes communicating with each other using language-agnostic APIs. These services are small, highly decoupled and focus on doing a small task, facilitating a modular approach to system-building.

But Wait

Isn't this just SOA?

Key Distinctions

  • Deployment
  • Scalability
  • Configuration

Deployment

  • Single artifact deployment
  • Independently / continuously deployable

Scalability

  • Independently scalable
  • Small, focused teams
  • Technology independence

Configuration

  • Convention over configuration
  • JEAS (Just Enough App Server)

Typical WildFly Deployment

Typical WildFly Deployment

OK, You Sold Me

But... How?

Terminology

Uberjar

A single .jar file containing your application, the portions of WildFly required to support it, an internal Maven repository of dependencies, plus a shim to bootstrap it all.

Fraction

A well-defined collection of application capabilities. May map directly to a WildFly subsystem, or bring in external capabilities such as Netflix Ribbon.

What Fractions Can Do

  • Enable WildFly subsystems (JAX-RS, Infinispan)
  • Provide deployments (ribbon-webapp, jolokia)
  • Alter deployments (keycloak)

Fractions

WildFly Subsystems

  • Datasources
  • EJB
  • JAX-RS
  • Transactions
  • Keycloak
  • Messaging
  • JPA
  • CDI
  • Undertow
  • Clustering
  • Infinispan
  • Hawkular

JAX-RS Fraction

pom.xml



  org.wildfly.swarm
  wildfly-swarm-jaxrs
  ${swarm.version}

          

A Swarm App

pom.xml



  org.wildfly.swarm
  wildfly-swarm-plugin
  
    
      
        package
      
    
  

          

Convert Java EE Application to Use WildFly Swarm

pom.xml





  org.wildfly.swarm
  wildfly-swarm-jaxrs-weld
  ${version.swarm}



  org.wildfly.swarm
  wildfly-swarm-jaxrs-jaxb
  ${version.swarm}




  org.wildfly.swarm
  wildfly-swarm-plugin
  ${version.swarm}
  
    
      
        package
      
    
  


          

That's All

Building a Swarm App

$ mvn package

Produces

target/myApp-swarm.jar

Running a Swarm App

$ java -jar myApp-swarm.jar

OR

$ mvn wildfly-swarm:run

Fractions

Not Just Java EE

Keycloak

  • WildFly Overlay
  • SSO, OAuth, OpenID, JWT, SAML, etc.

Keycloak Authentication

PricingResource.java


@Path("/")
public class PricingResource {

  @GET
  @Path("/book/{id}")
  @Produces("application/json")
  public Integer search(@PathParam("id") String id, @Context SecurityContext context) {
    KeycloakPrincipal principal = (KeycloakPrincipal) context.getUserPrincipal();
    if ( principal != null && principal.getKeycloakSecurityContext() != null ) {
      return 9;
    }
    return 10;
  }
}
          

Netflix OSS

  • Service Discovery
  • Client Side Load Balancing

Netflix OSS

Main.java


public class Main {

  public static void main(String... args) throws Exception {
    // Create a simple shrinkwrapped JAX-RS app
    Container container = new Container();
    JAXRSArchive deployment = ShrinkWrap.create(JAXRSArchive.class);
    deployment.addPackage(Main.class.getPackage());

    // Make it discoverable via Ribbon
    deployment.as(RibbonArchive.class).setApplicationName("pricing");
    deployment.as(Secured.class);

    container.start();
    container.deploy(deployment);
  }
}

          

Convention Over Configuration

  • Reasonable defaults out of the box
  • Easily customized with a fluent API

Custom Configuration


public class Main {

  public static void main(String...args) {

    CacheContainer webCache = new CacheContainer("web")
        .defaultCache("dist")
        .jgroupsTransport(new JGroupsTransport().lockTimeout(60000L))
        .distributedCache("dist", distCache -> distCache
            .mode("ASYNC")
            .l1Lifespan(0L)
            .owners(2)
            .lockingComponent(new LockingComponent().isolation("REPEATABLE_READ"))
            .transactionComponent(new TransactionComponent().mode("BATCH"))
            .fileStore(new FileStore()));

    InfinispanFraction fraction = new InfinispanFraction();
    fraction.cacheContainer( webCache );

    Container container = new Container();
    container.fraction( fraction );

    // Start the container
    container.start();
  }
}

Potential Hurdles

  • Complexity inherent in a distributed system
  • Potential operational complexity
  • Tooling

Transactions


public class Main {
  public static void main(String[] args) throws Exception {
    Container container = new Container();

    container.subsystem(new TransactionsFraction(4712, 4713));
    container.start();

    JAXRSArchive deployment = ShrinkWrap.create(JAXRSArchive.class);

    deployment.addResource(MyResource.class);

    container.deploy(deployment);
  }
}
          

Transactions


@Path("/")
public class MyResource {

  @Path("begincommit")
  @GET
  @Produces("text/plain")
  public String beginCommit() throws Exception {

    UserTransaction txn = (UserTransaction) new InitialContext()
        .lookup("java:comp/UserTransaction");
    String value = "Transaction ";

    try {
      txn.begin();

      value += "begun ok";

      try {
        txn.commit();

        value += " and committed ok";
      } catch (final Throwable ex) {
        value += " but failed to commit";
    }
  }
}
          

The Future

  • Formal release
  • More WildFly subsystems
  • Improved integration tests
  • Community feedback

Community

  • GitHub https://github.com/wildfly-swarm
  • Docs https://wildfly-swarm.gitbooks.io/wildfly-swarm-users-guide/content/
  • Twitter @wildflyswarm
  • Freenode #wildfly-swarm

Thanks & Questions