Microservices and Java EE



Microservices and Java EE

1 0


swarm-preso

Presentation for RHT Microservices Day in NYC, November 4 2015

On Github lance / swarm-preso

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

But Wait

Isn't this just SOA?

SOA is an architectural pattern where application components provide services to other components. In SOA those components can belong to the same application. With microservices these components are independent services.

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

<dependency>
  <groupid>org.wildfly.swarm</groupid>
  <artifactid>wildfly-swarm-jaxrs</artifactid>
  <version>${swarm.version}</version>
</dependency>

A Swarm App

pom.xml

<plugin>
  <groupid>org.wildfly.swarm</groupid>
  <artifactid>wildfly-swarm-plugin</artifactid>
  <executions>
    <execution>
      <goals>
        <goal>package</goal>
      </goals>
    </execution>
  </executions>
</plugin>

Convert Java EE Application to Use WildFly Swarm

pom.xml

<!-- include the JAX-RS with CDI+JAXB Fractions -->
<dependency>
  <groupid>org.wildfly.swarm</groupid>
  <artifactid>wildfly-swarm-jaxrs-weld</artifactid>
  <version>${version.swarm}</version>
</dependency>

<dependency>
  <groupid>org.wildfly.swarm</groupid>
  <artifactid>wildfly-swarm-jaxrs-jaxb</artifactid>
  <version>${version.swarm}</version>
</dependency>

<!-- Make it a Swarm App -->
<plugin>
  <groupid>org.wildfly.swarm</groupid>
  <artifactid>wildfly-swarm-plugin</artifactid>
  <version>${version.swarm}</version>
  <executions>
    <execution>
      <goals>
        <goal>package</goal>
      </goals>
    </execution>
  </executions>
</plugin>

That's All

Show local repo diff and run it here.

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

Microservices and Java EE Lance Ball / @lanceball