building microservices with wildfly swarm - qcon...
TRANSCRIPT
![Page 1: Building Microservices with WildFly Swarm - QCon Rioqconrio.com/rio2015/system/files/tutorial-slides/qconrio-workshop.pdf · Microservices • No limit on size ... • Propagates](https://reader034.vdocuments.net/reader034/viewer/2022050916/5a723b437f8b9abb538d5d35/html5/thumbnails/1.jpg)
Building Microservices with WildFly Swarm
Bob McWhirter QCon Rio
![Page 2: Building Microservices with WildFly Swarm - QCon Rioqconrio.com/rio2015/system/files/tutorial-slides/qconrio-workshop.pdf · Microservices • No limit on size ... • Propagates](https://reader034.vdocuments.net/reader034/viewer/2022050916/5a723b437f8b9abb538d5d35/html5/thumbnails/2.jpg)
Who is Bob?• Red Hat Middleware (JBoss)
• Director of Research & Prototyping
• Co-lead of WildFly Swarm
• Founder of…
• The Codehaus
• Drools
• TorqueBox
![Page 3: Building Microservices with WildFly Swarm - QCon Rioqconrio.com/rio2015/system/files/tutorial-slides/qconrio-workshop.pdf · Microservices • No limit on size ... • Propagates](https://reader034.vdocuments.net/reader034/viewer/2022050916/5a723b437f8b9abb538d5d35/html5/thumbnails/3.jpg)
Microservices
• Decoupled Components.
• Independent release cycles (continuous deployment).
• HTTP, REST or otherwise networked.
• Cattle, not pets.
![Page 4: Building Microservices with WildFly Swarm - QCon Rioqconrio.com/rio2015/system/files/tutorial-slides/qconrio-workshop.pdf · Microservices • No limit on size ... • Propagates](https://reader034.vdocuments.net/reader034/viewer/2022050916/5a723b437f8b9abb538d5d35/html5/thumbnails/4.jpg)
Microservices
• No limit on size, really.
• Micro functionality, not micro lines-of-code.
• Preferably self-contained.
• But not just Docker-izing everything.
![Page 5: Building Microservices with WildFly Swarm - QCon Rioqconrio.com/rio2015/system/files/tutorial-slides/qconrio-workshop.pdf · Microservices • No limit on size ... • Propagates](https://reader034.vdocuments.net/reader034/viewer/2022050916/5a723b437f8b9abb538d5d35/html5/thumbnails/5.jpg)
WildFly• Java-EE application-server
• ALL OF JAVA-EE
• So, it’s big.
• But it’s also fast, and awesome.
• Did I mention “big”?
![Page 6: Building Microservices with WildFly Swarm - QCon Rioqconrio.com/rio2015/system/files/tutorial-slides/qconrio-workshop.pdf · Microservices • No limit on size ... • Propagates](https://reader034.vdocuments.net/reader034/viewer/2022050916/5a723b437f8b9abb538d5d35/html5/thumbnails/6.jpg)
WildFly Swarm• WildFly, broken apart
• Maven-addressable components
• Fat-jarrable
• You can provide your own main(…)
• Programatic configuration (instead of standalone.xml)
![Page 7: Building Microservices with WildFly Swarm - QCon Rioqconrio.com/rio2015/system/files/tutorial-slides/qconrio-workshop.pdf · Microservices • No limit on size ... • Propagates](https://reader034.vdocuments.net/reader034/viewer/2022050916/5a723b437f8b9abb538d5d35/html5/thumbnails/7.jpg)
WildFly Swarm• Automatic configuration
• Convention over Configuration
• Beyond Java-EE
• Netflix Ribbon
• Logstash
![Page 8: Building Microservices with WildFly Swarm - QCon Rioqconrio.com/rio2015/system/files/tutorial-slides/qconrio-workshop.pdf · Microservices • No limit on size ... • Propagates](https://reader034.vdocuments.net/reader034/viewer/2022050916/5a723b437f8b9abb538d5d35/html5/thumbnails/8.jpg)
Example Application
Booker
![Page 9: Building Microservices with WildFly Swarm - QCon Rioqconrio.com/rio2015/system/files/tutorial-slides/qconrio-workshop.pdf · Microservices • No limit on size ... • Propagates](https://reader034.vdocuments.net/reader034/viewer/2022050916/5a723b437f8b9abb538d5d35/html5/thumbnails/9.jpg)
• Akin to the Amazon Kindle Store
• Search for books
• Get price for books
• Buy books
• Keep your library of purchased books
![Page 10: Building Microservices with WildFly Swarm - QCon Rioqconrio.com/rio2015/system/files/tutorial-slides/qconrio-workshop.pdf · Microservices • No limit on size ... • Propagates](https://reader034.vdocuments.net/reader034/viewer/2022050916/5a723b437f8b9abb538d5d35/html5/thumbnails/10.jpg)
• Authentication using Keycloak
• Logging using Logstash
• React.js single-page-app Web UI
• Inter-service communication using Ribbon
• From Java and Javascript
![Page 11: Building Microservices with WildFly Swarm - QCon Rioqconrio.com/rio2015/system/files/tutorial-slides/qconrio-workshop.pdf · Microservices • No limit on size ... • Propagates](https://reader034.vdocuments.net/reader034/viewer/2022050916/5a723b437f8b9abb538d5d35/html5/thumbnails/11.jpg)
Clone Booker
• GitHub: https://github.com/wildfly-swarm/booker
• git clone https://github.com/wildfly-swarm/booker.git
![Page 12: Building Microservices with WildFly Swarm - QCon Rioqconrio.com/rio2015/system/files/tutorial-slides/qconrio-workshop.pdf · Microservices • No limit on size ... • Propagates](https://reader034.vdocuments.net/reader034/viewer/2022050916/5a723b437f8b9abb538d5d35/html5/thumbnails/12.jpg)
Keycloak
![Page 13: Building Microservices with WildFly Swarm - QCon Rioqconrio.com/rio2015/system/files/tutorial-slides/qconrio-workshop.pdf · Microservices • No limit on size ... • Propagates](https://reader034.vdocuments.net/reader034/viewer/2022050916/5a723b437f8b9abb538d5d35/html5/thumbnails/13.jpg)
Keycloak
• Single-sign-on
• Supports social login
• Bearer tokens for automated access
• Token propagation for chained service invocations
![Page 14: Building Microservices with WildFly Swarm - QCon Rioqconrio.com/rio2015/system/files/tutorial-slides/qconrio-workshop.pdf · Microservices • No limit on size ... • Propagates](https://reader034.vdocuments.net/reader034/viewer/2022050916/5a723b437f8b9abb538d5d35/html5/thumbnails/14.jpg)
• $BOOKER_ROOT/extra/keycloak/README.md
• http://downloads.jboss.org/keycloak/1.4.0.Final/keycloak-1.4.0.Final.zip
• Unzip
• cd keycloak-1.4.0.Final/
• ./bin/standalone.sh -Djboss.http.port=9090
![Page 16: Building Microservices with WildFly Swarm - QCon Rioqconrio.com/rio2015/system/files/tutorial-slides/qconrio-workshop.pdf · Microservices • No limit on size ... • Propagates](https://reader034.vdocuments.net/reader034/viewer/2022050916/5a723b437f8b9abb538d5d35/html5/thumbnails/16.jpg)
![Page 17: Building Microservices with WildFly Swarm - QCon Rioqconrio.com/rio2015/system/files/tutorial-slides/qconrio-workshop.pdf · Microservices • No limit on size ... • Propagates](https://reader034.vdocuments.net/reader034/viewer/2022050916/5a723b437f8b9abb538d5d35/html5/thumbnails/17.jpg)
![Page 18: Building Microservices with WildFly Swarm - QCon Rioqconrio.com/rio2015/system/files/tutorial-slides/qconrio-workshop.pdf · Microservices • No limit on size ... • Propagates](https://reader034.vdocuments.net/reader034/viewer/2022050916/5a723b437f8b9abb538d5d35/html5/thumbnails/18.jpg)
Keycloak• Managed separate from your application
• Organization-wide
• Can delegate to Kerberos, LDAP, etc
• Can do social login (Twitter, GitHub, etc)
• Deserves its own workshop, really…
![Page 19: Building Microservices with WildFly Swarm - QCon Rioqconrio.com/rio2015/system/files/tutorial-slides/qconrio-workshop.pdf · Microservices • No limit on size ... • Propagates](https://reader034.vdocuments.net/reader034/viewer/2022050916/5a723b437f8b9abb538d5d35/html5/thumbnails/19.jpg)
Web Client
![Page 20: Building Microservices with WildFly Swarm - QCon Rioqconrio.com/rio2015/system/files/tutorial-slides/qconrio-workshop.pdf · Microservices • No limit on size ... • Propagates](https://reader034.vdocuments.net/reader034/viewer/2022050916/5a723b437f8b9abb538d5d35/html5/thumbnails/20.jpg)
Web Client
• Single-Page Application
• React.js to draw the pages
• Reflux to manage state
• React-Router for routing requests without reloads
![Page 21: Building Microservices with WildFly Swarm - QCon Rioqconrio.com/rio2015/system/files/tutorial-slides/qconrio-workshop.pdf · Microservices • No limit on size ... • Propagates](https://reader034.vdocuments.net/reader034/viewer/2022050916/5a723b437f8b9abb538d5d35/html5/thumbnails/21.jpg)
React.js
• Just the view portion
• Virtual DOM, straightforward to update browser
• We’re using .jsx compiler in the browser, for simplicity. DO NOT USE FOR PRODUCTION
• Deserves its own workshop, really…
![Page 22: Building Microservices with WildFly Swarm - QCon Rioqconrio.com/rio2015/system/files/tutorial-slides/qconrio-workshop.pdf · Microservices • No limit on size ... • Propagates](https://reader034.vdocuments.net/reader034/viewer/2022050916/5a723b437f8b9abb538d5d35/html5/thumbnails/22.jpg)
Other Bits
• Reflux
• Handles updating the view when state changes
• React-Router
• Handles updating the view when the URL changes
![Page 23: Building Microservices with WildFly Swarm - QCon Rioqconrio.com/rio2015/system/files/tutorial-slides/qconrio-workshop.pdf · Microservices • No limit on size ... • Propagates](https://reader034.vdocuments.net/reader034/viewer/2022050916/5a723b437f8b9abb538d5d35/html5/thumbnails/23.jpg)
Web Client
<packaging>war</packaging>
![Page 24: Building Microservices with WildFly Swarm - QCon Rioqconrio.com/rio2015/system/files/tutorial-slides/qconrio-workshop.pdf · Microservices • No limit on size ... • Propagates](https://reader034.vdocuments.net/reader034/viewer/2022050916/5a723b437f8b9abb538d5d35/html5/thumbnails/24.jpg)
Web Client
No main(…)
![Page 25: Building Microservices with WildFly Swarm - QCon Rioqconrio.com/rio2015/system/files/tutorial-slides/qconrio-workshop.pdf · Microservices • No limit on size ... • Propagates](https://reader034.vdocuments.net/reader034/viewer/2022050916/5a723b437f8b9abb538d5d35/html5/thumbnails/25.jpg)
Web Client
<dependency> <groupId>org.wildfly.swarm</groupId> <artifactId>wildfly-swarm-undertow</artifactId></dependency>
![Page 26: Building Microservices with WildFly Swarm - QCon Rioqconrio.com/rio2015/system/files/tutorial-slides/qconrio-workshop.pdf · Microservices • No limit on size ... • Propagates](https://reader034.vdocuments.net/reader034/viewer/2022050916/5a723b437f8b9abb538d5d35/html5/thumbnails/26.jpg)
Web Client
mvn wildfly-swarm:run
![Page 27: Building Microservices with WildFly Swarm - QCon Rioqconrio.com/rio2015/system/files/tutorial-slides/qconrio-workshop.pdf · Microservices • No limit on size ... • Propagates](https://reader034.vdocuments.net/reader034/viewer/2022050916/5a723b437f8b9abb538d5d35/html5/thumbnails/27.jpg)
![Page 29: Building Microservices with WildFly Swarm - QCon Rioqconrio.com/rio2015/system/files/tutorial-slides/qconrio-workshop.pdf · Microservices • No limit on size ... • Propagates](https://reader034.vdocuments.net/reader034/viewer/2022050916/5a723b437f8b9abb538d5d35/html5/thumbnails/29.jpg)
But nothing actually works.
![Page 30: Building Microservices with WildFly Swarm - QCon Rioqconrio.com/rio2015/system/files/tutorial-slides/qconrio-workshop.pdf · Microservices • No limit on size ... • Propagates](https://reader034.vdocuments.net/reader034/viewer/2022050916/5a723b437f8b9abb538d5d35/html5/thumbnails/30.jpg)
Store
![Page 31: Building Microservices with WildFly Swarm - QCon Rioqconrio.com/rio2015/system/files/tutorial-slides/qconrio-workshop.pdf · Microservices • No limit on size ... • Propagates](https://reader034.vdocuments.net/reader034/viewer/2022050916/5a723b437f8b9abb538d5d35/html5/thumbnails/31.jpg)
Store
• JAX-RS StoreResource
• CDI-injected Store
• We provide a main(…)
• Uses Ribbon
![Page 32: Building Microservices with WildFly Swarm - QCon Rioqconrio.com/rio2015/system/files/tutorial-slides/qconrio-workshop.pdf · Microservices • No limit on size ... • Propagates](https://reader034.vdocuments.net/reader034/viewer/2022050916/5a723b437f8b9abb538d5d35/html5/thumbnails/32.jpg)
Store
<dependency> <groupId>org.wildfly.swarm</groupId> <artifactId>wildfly-swarm-jaxrs-weld</artifactId></dependency>
![Page 33: Building Microservices with WildFly Swarm - QCon Rioqconrio.com/rio2015/system/files/tutorial-slides/qconrio-workshop.pdf · Microservices • No limit on size ... • Propagates](https://reader034.vdocuments.net/reader034/viewer/2022050916/5a723b437f8b9abb538d5d35/html5/thumbnails/33.jpg)
Store01 Container container = new Container();02 03 JAXRSArchive deployment = ShrinkWrap.create(JAXRSArchive.class); 04 05 deployment.addPackage(Main.class.getPackage()); 06 07 deployment.as(RibbonArchive.class).setApplicationName("store");08 09 deployment.as(Secured.class);10 11 deployment.addAllDependencies();12 13 container.start();14 15 container.deploy(deployment);
![Page 34: Building Microservices with WildFly Swarm - QCon Rioqconrio.com/rio2015/system/files/tutorial-slides/qconrio-workshop.pdf · Microservices • No limit on size ... • Propagates](https://reader034.vdocuments.net/reader034/viewer/2022050916/5a723b437f8b9abb538d5d35/html5/thumbnails/34.jpg)
Store@Path("/") public class StoreResource { @Inject private Store store; @Inject private PricingService pricingService; @GET @Path("/search") @Produces("application/json") public Store.SearchResult search(@QueryParam("q") String q, @QueryParam("page") Integer page) { . . . } @GET @Path("/book") @Produces("application/json") public void get(@Suspended final AsyncResponse asyncResponse, @QueryParam("id") String id) { . . . } }
![Page 35: Building Microservices with WildFly Swarm - QCon Rioqconrio.com/rio2015/system/files/tutorial-slides/qconrio-workshop.pdf · Microservices • No limit on size ... • Propagates](https://reader034.vdocuments.net/reader034/viewer/2022050916/5a723b437f8b9abb538d5d35/html5/thumbnails/35.jpg)
StoreResource
@Injectprivate Store store;
![Page 36: Building Microservices with WildFly Swarm - QCon Rioqconrio.com/rio2015/system/files/tutorial-slides/qconrio-workshop.pdf · Microservices • No limit on size ... • Propagates](https://reader034.vdocuments.net/reader034/viewer/2022050916/5a723b437f8b9abb538d5d35/html5/thumbnails/36.jpg)
Store
@ApplicationScopedpublic class Store {
public Book get(String id) { . . . } public SearchResult search(String q, int page) { . . . }
}
![Page 37: Building Microservices with WildFly Swarm - QCon Rioqconrio.com/rio2015/system/files/tutorial-slides/qconrio-workshop.pdf · Microservices • No limit on size ... • Propagates](https://reader034.vdocuments.net/reader034/viewer/2022050916/5a723b437f8b9abb538d5d35/html5/thumbnails/37.jpg)
Store
• Our main(…) builds the deployment
• Since we have wildfly-swarm-jaxrs-weld we
• …don’t have to provide an Application
• …can use CDI
![Page 38: Building Microservices with WildFly Swarm - QCon Rioqconrio.com/rio2015/system/files/tutorial-slides/qconrio-workshop.pdf · Microservices • No limit on size ... • Propagates](https://reader034.vdocuments.net/reader034/viewer/2022050916/5a723b437f8b9abb538d5d35/html5/thumbnails/38.jpg)
Stores have prices, though…
![Page 39: Building Microservices with WildFly Swarm - QCon Rioqconrio.com/rio2015/system/files/tutorial-slides/qconrio-workshop.pdf · Microservices • No limit on size ... • Propagates](https://reader034.vdocuments.net/reader034/viewer/2022050916/5a723b437f8b9abb538d5d35/html5/thumbnails/39.jpg)
NetflixOSS Ribbon
![Page 40: Building Microservices with WildFly Swarm - QCon Rioqconrio.com/rio2015/system/files/tutorial-slides/qconrio-workshop.pdf · Microservices • No limit on size ... • Propagates](https://reader034.vdocuments.net/reader034/viewer/2022050916/5a723b437f8b9abb538d5d35/html5/thumbnails/40.jpg)
Ribbon
• Client-side load-balancing to other services
• Reference service by name, not host
• Allows Java interface for invoking service
![Page 41: Building Microservices with WildFly Swarm - QCon Rioqconrio.com/rio2015/system/files/tutorial-slides/qconrio-workshop.pdf · Microservices • No limit on size ... • Propagates](https://reader034.vdocuments.net/reader034/viewer/2022050916/5a723b437f8b9abb538d5d35/html5/thumbnails/41.jpg)
Ribbon
@ResourceGroup(name="pricing") public interface PricingService { @TemplateName("get") @Http( method = Http.HttpMethod.GET, uri = "/book/{id}" ) RibbonRequest<ByteBuf> get(@Var("id") String id); }
![Page 42: Building Microservices with WildFly Swarm - QCon Rioqconrio.com/rio2015/system/files/tutorial-slides/qconrio-workshop.pdf · Microservices • No limit on size ... • Propagates](https://reader034.vdocuments.net/reader034/viewer/2022050916/5a723b437f8b9abb538d5d35/html5/thumbnails/42.jpg)
Ribbon
pricingService.get( “42” )
GET http://${HOST}/book/42
![Page 43: Building Microservices with WildFly Swarm - QCon Rioqconrio.com/rio2015/system/files/tutorial-slides/qconrio-workshop.pdf · Microservices • No limit on size ... • Propagates](https://reader034.vdocuments.net/reader034/viewer/2022050916/5a723b437f8b9abb538d5d35/html5/thumbnails/43.jpg)
Store
@ApplicationScopedpublic class ServicesFactory { @Produces @ApplicationScoped public static PricingService getInstance() { return SecuredRibbon.from(PricingService.class); }}
![Page 44: Building Microservices with WildFly Swarm - QCon Rioqconrio.com/rio2015/system/files/tutorial-slides/qconrio-workshop.pdf · Microservices • No limit on size ... • Propagates](https://reader034.vdocuments.net/reader034/viewer/2022050916/5a723b437f8b9abb538d5d35/html5/thumbnails/44.jpg)
SecuredRibbon• Provided by WildFly Swarm
• Emulates original Ribbon class
• Has exactly 1 method: .from(someInterface)
• Wires up the interface with WildFly Clustering to know where services live
• Propagates Keycloak authentication tokens to the invocation
![Page 45: Building Microservices with WildFly Swarm - QCon Rioqconrio.com/rio2015/system/files/tutorial-slides/qconrio-workshop.pdf · Microservices • No limit on size ... • Propagates](https://reader034.vdocuments.net/reader034/viewer/2022050916/5a723b437f8b9abb538d5d35/html5/thumbnails/45.jpg)
Pricing
![Page 46: Building Microservices with WildFly Swarm - QCon Rioqconrio.com/rio2015/system/files/tutorial-slides/qconrio-workshop.pdf · Microservices • No limit on size ... • Propagates](https://reader034.vdocuments.net/reader034/viewer/2022050916/5a723b437f8b9abb538d5d35/html5/thumbnails/46.jpg)
Pricing
• Service just to demonstrate Ribbon + Keycloak
• If a request is un-authenticated, returns $10
• If a request is authenticated, returns $9
![Page 47: Building Microservices with WildFly Swarm - QCon Rioqconrio.com/rio2015/system/files/tutorial-slides/qconrio-workshop.pdf · Microservices • No limit on size ... • Propagates](https://reader034.vdocuments.net/reader034/viewer/2022050916/5a723b437f8b9abb538d5d35/html5/thumbnails/47.jpg)
Pricing
@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; }}
![Page 48: Building Microservices with WildFly Swarm - QCon Rioqconrio.com/rio2015/system/files/tutorial-slides/qconrio-workshop.pdf · Microservices • No limit on size ... • Propagates](https://reader034.vdocuments.net/reader034/viewer/2022050916/5a723b437f8b9abb538d5d35/html5/thumbnails/48.jpg)
Web Client
Keycloak
store pricing
![Page 49: Building Microservices with WildFly Swarm - QCon Rioqconrio.com/rio2015/system/files/tutorial-slides/qconrio-workshop.pdf · Microservices • No limit on size ... • Propagates](https://reader034.vdocuments.net/reader034/viewer/2022050916/5a723b437f8b9abb538d5d35/html5/thumbnails/49.jpg)
Ribbon Requests
Observable<ByteBuf> obs = service.method(params).observe(); obs.subscribe( (result) -> { // result is a ByteBuf . . . }, (err) -> { // err is an Exception . . . } );
![Page 50: Building Microservices with WildFly Swarm - QCon Rioqconrio.com/rio2015/system/files/tutorial-slides/qconrio-workshop.pdf · Microservices • No limit on size ... • Propagates](https://reader034.vdocuments.net/reader034/viewer/2022050916/5a723b437f8b9abb538d5d35/html5/thumbnails/50.jpg)
Ribbon Requests@GET@Path("/book") @Produces("application/json") public void get(@Suspended final AsyncResponse asyncResponse, @QueryParam("id") String id) { Book book = this.store.get(id); Observable<ByteBuf> obs = pricingService.get(id).observe(); obs.subscribe( (result) -> { int price = Integer.parseInt(result.toString(UTF8)); book.setPrice(price); asyncResponse.resume(book); }, (err) -> { asyncResponse.resume(err); } );}
![Page 51: Building Microservices with WildFly Swarm - QCon Rioqconrio.com/rio2015/system/files/tutorial-slides/qconrio-workshop.pdf · Microservices • No limit on size ... • Propagates](https://reader034.vdocuments.net/reader034/viewer/2022050916/5a723b437f8b9abb538d5d35/html5/thumbnails/51.jpg)
Back to Keycloak…
![Page 52: Building Microservices with WildFly Swarm - QCon Rioqconrio.com/rio2015/system/files/tutorial-slides/qconrio-workshop.pdf · Microservices • No limit on size ... • Propagates](https://reader034.vdocuments.net/reader034/viewer/2022050916/5a723b437f8b9abb538d5d35/html5/thumbnails/52.jpg)
Securing from .js
keycloak.init({ onLoad: 'check-sso' }).success( function() { if ( keycloak.authenticated ) { keycloak.loadUserInfo().success( function(info) { Booker.Actions.UserLoggedIn( info ); }); } Router.run(routes, Router.HistoryLocation, function (Handler) { React.render(<Handler/>, document.getElementById('app')); });})
![Page 53: Building Microservices with WildFly Swarm - QCon Rioqconrio.com/rio2015/system/files/tutorial-slides/qconrio-workshop.pdf · Microservices • No limit on size ... • Propagates](https://reader034.vdocuments.net/reader034/viewer/2022050916/5a723b437f8b9abb538d5d35/html5/thumbnails/53.jpg)
Keycloak
• We check-sso when we initialize Keycloak
• Bounces user to Keycloak to see if they are auth’d
![Page 54: Building Microservices with WildFly Swarm - QCon Rioqconrio.com/rio2015/system/files/tutorial-slides/qconrio-workshop.pdf · Microservices • No limit on size ... • Propagates](https://reader034.vdocuments.net/reader034/viewer/2022050916/5a723b437f8b9abb538d5d35/html5/thumbnails/54.jpg)
Secure Requests from .js
if ( keycloak.token ) { headers.Authorization = 'Bearer ' + keycloak.token;}
![Page 55: Building Microservices with WildFly Swarm - QCon Rioqconrio.com/rio2015/system/files/tutorial-slides/qconrio-workshop.pdf · Microservices • No limit on size ... • Propagates](https://reader034.vdocuments.net/reader034/viewer/2022050916/5a723b437f8b9abb538d5d35/html5/thumbnails/55.jpg)
Ribbon from .js
• Ribbon in Java uses WildFly Clustering to wire together services.
• What about Javascript?
![Page 56: Building Microservices with WildFly Swarm - QCon Rioqconrio.com/rio2015/system/files/tutorial-slides/qconrio-workshop.pdf · Microservices • No limit on size ... • Propagates](https://reader034.vdocuments.net/reader034/viewer/2022050916/5a723b437f8b9abb538d5d35/html5/thumbnails/56.jpg)
RibbonToTheCurb
• An async servlet in the web-client WAR
• Serves Ribbon topology information to the single-page-app via Server-Sent-Events (SSE)
![Page 57: Building Microservices with WildFly Swarm - QCon Rioqconrio.com/rio2015/system/files/tutorial-slides/qconrio-workshop.pdf · Microservices • No limit on size ... • Propagates](https://reader034.vdocuments.net/reader034/viewer/2022050916/5a723b437f8b9abb538d5d35/html5/thumbnails/57.jpg)
RibbonToTheCurbthis.topology = (RibbonTopology) context.lookup("jboss/ribbon/cluster");
. . .
resp.setContentType("text/event-stream"); resp.setCharacterEncoding("UTF-8"); AsyncContext asyncContext = req.startAsync();PrintWriter writer = resp.getWriter();
RibbonTopologyListener topologyListener = new RibbonTopologyListener() { @Override public void onChange(RibbonTopology topology) { String json = topologyToJson(); writer.write( "data: " + json ); writer.flush(); }};
![Page 59: Building Microservices with WildFly Swarm - QCon Rioqconrio.com/rio2015/system/files/tutorial-slides/qconrio-workshop.pdf · Microservices • No limit on size ... • Propagates](https://reader034.vdocuments.net/reader034/viewer/2022050916/5a723b437f8b9abb538d5d35/html5/thumbnails/59.jpg)
RibbonToTheCurb
• Service end-points don’t have to be encoded into the Javascript
• If end-points move, go up, go down, that’s okay
• Topology changes are immediately known by the web clients
![Page 60: Building Microservices with WildFly Swarm - QCon Rioqconrio.com/rio2015/system/files/tutorial-slides/qconrio-workshop.pdf · Microservices • No limit on size ... • Propagates](https://reader034.vdocuments.net/reader034/viewer/2022050916/5a723b437f8b9abb538d5d35/html5/thumbnails/60.jpg)
ribbon.jsRibbon.ajax = function(serviceName, url, settings) { var allServers = Booker.State.Topology.servers( serviceName ); if ( ! settings ) { settings = {}; } var headers = settings.headers || {}; if ( keycloak.token ) { headers.Authorization = 'Bearer ' + keycloak.token } settings.url = '//' + allServers[0] + url; settings.headers = headers; if ( allServers.length > 0 ) { return $.ajax( settings ); } var deferred = $.Deferred(); return deferred.reject();}
![Page 61: Building Microservices with WildFly Swarm - QCon Rioqconrio.com/rio2015/system/files/tutorial-slides/qconrio-workshop.pdf · Microservices • No limit on size ... • Propagates](https://reader034.vdocuments.net/reader034/viewer/2022050916/5a723b437f8b9abb538d5d35/html5/thumbnails/61.jpg)
ribbon.js
• Uses jQuery to perform AJAX requests
• Mixes in Keycloak bearer token (if present)
• Selects server from list provided by Ribbon
• Works with the promises API (from jQuery)
![Page 62: Building Microservices with WildFly Swarm - QCon Rioqconrio.com/rio2015/system/files/tutorial-slides/qconrio-workshop.pdf · Microservices • No limit on size ... • Propagates](https://reader034.vdocuments.net/reader034/viewer/2022050916/5a723b437f8b9abb538d5d35/html5/thumbnails/62.jpg)
Library
![Page 63: Building Microservices with WildFly Swarm - QCon Rioqconrio.com/rio2015/system/files/tutorial-slides/qconrio-workshop.pdf · Microservices • No limit on size ... • Propagates](https://reader034.vdocuments.net/reader034/viewer/2022050916/5a723b437f8b9abb538d5d35/html5/thumbnails/63.jpg)
Library
• JAX-RS Service
• Requires authentication
• JPA to store user/book associations for purchases
• Invokes the store service for book titles
![Page 64: Building Microservices with WildFly Swarm - QCon Rioqconrio.com/rio2015/system/files/tutorial-slides/qconrio-workshop.pdf · Microservices • No limit on size ... • Propagates](https://reader034.vdocuments.net/reader034/viewer/2022050916/5a723b437f8b9abb538d5d35/html5/thumbnails/64.jpg)
Library
Container container = new Container();
container.fraction(new JPAFraction() .inhibitDefaultDatasource() .defaultDatasourceName(“LibraryDS")); container.fraction(new DatasourcesFraction() .driver(new Driver("h2") .datasourceClassName("org.h2.Driver") .xaDatasourceClassName("org.h2.jdbcx.JdbcDataSource") .module("com.h2database.h2")) .datasource(new Datasource("LibraryDS") .driver("h2") .connectionURL("jdbc:h2:./library;DB_CLOSE_ON_EXIT=TRUE") .authentication("sa", "sa")));
![Page 65: Building Microservices with WildFly Swarm - QCon Rioqconrio.com/rio2015/system/files/tutorial-slides/qconrio-workshop.pdf · Microservices • No limit on size ... • Propagates](https://reader034.vdocuments.net/reader034/viewer/2022050916/5a723b437f8b9abb538d5d35/html5/thumbnails/65.jpg)
Library
JAXRSArchive deployment = ShrinkWrap.create(JAXRSArchive.class);deployment.addPackage(Main.class.getPackage());deployment.as(RibbonArchive.class).setApplicationName("library");deployment.as(Secured.class) .protect("/items") .withMethod("GET") .withRole("*");
![Page 66: Building Microservices with WildFly Swarm - QCon Rioqconrio.com/rio2015/system/files/tutorial-slides/qconrio-workshop.pdf · Microservices • No limit on size ... • Propagates](https://reader034.vdocuments.net/reader034/viewer/2022050916/5a723b437f8b9abb538d5d35/html5/thumbnails/66.jpg)
Librarydeployment.add(new ClassLoaderAsset("META-INF/persistence.xml", Main.class.getClassLoader()), “WEB-INF/classes/META-INF/persistence.xml");
<?xml version="1.0" encoding="UTF-8"?><persistence xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="2.1" xmlns="http://xmlns.jcp.org/xml/ns/persistence" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/persistence http://xmlns.jcp.org/xml/ns/persistence/persistence_2_1.xsd"> <persistence-unit name="LibraryPU" transaction-type="JTA"> <properties> </properties> </persistence-unit> </persistence>
![Page 67: Building Microservices with WildFly Swarm - QCon Rioqconrio.com/rio2015/system/files/tutorial-slides/qconrio-workshop.pdf · Microservices • No limit on size ... • Propagates](https://reader034.vdocuments.net/reader034/viewer/2022050916/5a723b437f8b9abb538d5d35/html5/thumbnails/67.jpg)
Library@Entity@Table(name="LibraryItem") public class LibraryItem { @Id @GeneratedValue(strategy = GenerationType.AUTO) private int id; @Column private String userId; @Column private String bookId; @Transient private String title; @Transient private String author; public LibraryItem() { } public LibraryItem(String userId, String bookId) { this.userId = userId; this.bookId = bookId; }
. . .}
![Page 68: Building Microservices with WildFly Swarm - QCon Rioqconrio.com/rio2015/system/files/tutorial-slides/qconrio-workshop.pdf · Microservices • No limit on size ... • Propagates](https://reader034.vdocuments.net/reader034/viewer/2022050916/5a723b437f8b9abb538d5d35/html5/thumbnails/68.jpg)
Library@Path("/") @Statelesspublic class LibraryResource { @Inject StoreService store; @Inject EntityManager em; @GET @Produces("application/json") @Path("/items") public void get(@Suspended final AsyncResponse asyncResponse, @Context SecurityContext context) { . . . } @POST @Produces("application/json") @Path("/items") public LibraryItem addItem(@Context SecurityContext context, @FormParam("id") String bookId) throws URISyntaxException { . . . } }
![Page 69: Building Microservices with WildFly Swarm - QCon Rioqconrio.com/rio2015/system/files/tutorial-slides/qconrio-workshop.pdf · Microservices • No limit on size ... • Propagates](https://reader034.vdocuments.net/reader034/viewer/2022050916/5a723b437f8b9abb538d5d35/html5/thumbnails/69.jpg)
Library
@POST@Produces("application/json") @Path("/items") public LibraryItem addItem(@Context SecurityContext context, @FormParam("id") String bookId) throws URISyntaxException { KeycloakPrincipal principal = (KeycloakPrincipal) context.getUserPrincipal(); String userId = principal.getName(); LibraryItem item = new LibraryItem(userId, bookId); em.persist(item); return item;}
![Page 70: Building Microservices with WildFly Swarm - QCon Rioqconrio.com/rio2015/system/files/tutorial-slides/qconrio-workshop.pdf · Microservices • No limit on size ... • Propagates](https://reader034.vdocuments.net/reader034/viewer/2022050916/5a723b437f8b9abb538d5d35/html5/thumbnails/70.jpg)
But that’s only userId+bookId
![Page 71: Building Microservices with WildFly Swarm - QCon Rioqconrio.com/rio2015/system/files/tutorial-slides/qconrio-workshop.pdf · Microservices • No limit on size ... • Propagates](https://reader034.vdocuments.net/reader034/viewer/2022050916/5a723b437f8b9abb538d5d35/html5/thumbnails/71.jpg)
Web Client
Keycloak
store pricing
library
![Page 72: Building Microservices with WildFly Swarm - QCon Rioqconrio.com/rio2015/system/files/tutorial-slides/qconrio-workshop.pdf · Microservices • No limit on size ... • Propagates](https://reader034.vdocuments.net/reader034/viewer/2022050916/5a723b437f8b9abb538d5d35/html5/thumbnails/72.jpg)
Library
@ResourceGroup(name = "store") public interface StoreService { @TemplateName("get") @Http( method = Http.HttpMethod.GET, uri = "/book?id={bookId}" ) RibbonRequest<ByteBuf> get(@Var("bookId")String bookId);}
![Page 73: Building Microservices with WildFly Swarm - QCon Rioqconrio.com/rio2015/system/files/tutorial-slides/qconrio-workshop.pdf · Microservices • No limit on size ... • Propagates](https://reader034.vdocuments.net/reader034/viewer/2022050916/5a723b437f8b9abb538d5d35/html5/thumbnails/73.jpg)
Library
@ApplicationScopedpublic class ServicesFactory { @Produces @ApplicationScoped public static StoreService getInstance() { return SecuredRibbon.from(StoreService.class); }}
![Page 74: Building Microservices with WildFly Swarm - QCon Rioqconrio.com/rio2015/system/files/tutorial-slides/qconrio-workshop.pdf · Microservices • No limit on size ... • Propagates](https://reader034.vdocuments.net/reader034/viewer/2022050916/5a723b437f8b9abb538d5d35/html5/thumbnails/74.jpg)
Library
@GET@Produces("application/json") @Path("/items") public void get(@Suspended final AsyncResponse asyncResponse, @Context SecurityContext context) { KeycloakPrincipal principal = (KeycloakPrincipal) context.getUserPrincipal(); String userId = principal.getName(); TypedQuery<LibraryItem> q = this.em.createQuery( "SELECT li FROM LibraryItem li WHERE li.userId = :userId”, LibraryItem.class); List<LibraryItem> items = q.setParameter("userId", userId) .getResultList();
![Page 75: Building Microservices with WildFly Swarm - QCon Rioqconrio.com/rio2015/system/files/tutorial-slides/qconrio-workshop.pdf · Microservices • No limit on size ... • Propagates](https://reader034.vdocuments.net/reader034/viewer/2022050916/5a723b437f8b9abb538d5d35/html5/thumbnails/75.jpg)
How do we populate titles in that list?
![Page 76: Building Microservices with WildFly Swarm - QCon Rioqconrio.com/rio2015/system/files/tutorial-slides/qconrio-workshop.pdf · Microservices • No limit on size ... • Propagates](https://reader034.vdocuments.net/reader034/viewer/2022050916/5a723b437f8b9abb538d5d35/html5/thumbnails/76.jpg)
Libraryfor (LibraryItem each : items) { Observable<ByteBuf> obs = store.get(each.getBookId()).observe(); root = root.zipWith(obs, new Func2<List<LibraryItem>, ByteBuf, List<LibraryItem>>() { @Override public List<LibraryItem> call(List<LibraryItem> libraryItems, ByteBuf byteBuf) { ObjectMapper mapper = new ObjectMapper(); ObjectReader reader = mapper.reader(); JsonFactory factory = new JsonFactory(); try { JsonParser parser = factory.createParser(new ByteBufInputStream(byteBuf)); Map map = reader.readValue(parser, Map.class); each.setTitle((String) map.get("title")); each.setAuthor((String) map.get("author")); } catch (IOException e) { } libraryItems.add(each); return libraryItems; } });}
![Page 77: Building Microservices with WildFly Swarm - QCon Rioqconrio.com/rio2015/system/files/tutorial-slides/qconrio-workshop.pdf · Microservices • No limit on size ... • Propagates](https://reader034.vdocuments.net/reader034/viewer/2022050916/5a723b437f8b9abb538d5d35/html5/thumbnails/77.jpg)
Fire off Requests
for (LibraryItem each : items) { Observable<ByteBuf> obs = store.get(each.getBookId()).observe(); . . . }
![Page 78: Building Microservices with WildFly Swarm - QCon Rioqconrio.com/rio2015/system/files/tutorial-slides/qconrio-workshop.pdf · Microservices • No limit on size ... • Propagates](https://reader034.vdocuments.net/reader034/viewer/2022050916/5a723b437f8b9abb538d5d35/html5/thumbnails/78.jpg)
Observable<List<LibraryItem>> root = Observable.just(new ArrayList<>()); . . .
for (LibraryItem each : items) { Observable<ByteBuf> obs = store.get(each.getBookId()).observe(); root = root.zipWith(obs, ((libraryItems, byteBuf) -> { ObjectMapper mapper = new ObjectMapper(); ObjectReader reader = mapper.reader(); JsonFactory factory = new JsonFactory(); try { JsonParser parser = factory.createParser(new ByteBufInputStream(byteBuf)); Map map = reader.readValue(parser, Map.class); each.setTitle((String) map.get("title")); each.setAuthor((String) map.get("author")); } catch (IOException e) { } libraryItems.add(each); return libraryItems; }));}
Zip them together
![Page 79: Building Microservices with WildFly Swarm - QCon Rioqconrio.com/rio2015/system/files/tutorial-slides/qconrio-workshop.pdf · Microservices • No limit on size ... • Propagates](https://reader034.vdocuments.net/reader034/viewer/2022050916/5a723b437f8b9abb538d5d35/html5/thumbnails/79.jpg)
Observable<List<LibraryItem>> root = Observable.just(new ArrayList<>()); . . .
for (LibraryItem each : items) { Observable<ByteBuf> obs = store.get(each.getBookId()).observe(); root = root.zipWith(obs, ((libraryItems, byteBuf) -> { ObjectMapper mapper = new ObjectMapper(); ObjectReader reader = mapper.reader(); JsonFactory factory = new JsonFactory(); try { JsonParser parser = factory.createParser(new ByteBufInputStream(byteBuf)); Map map = reader.readValue(parser, Map.class); each.setTitle((String) map.get("title")); each.setAuthor((String) map.get("author")); } catch (IOException e) { } libraryItems.add(each); return libraryItems; }));}
Process each response
![Page 80: Building Microservices with WildFly Swarm - QCon Rioqconrio.com/rio2015/system/files/tutorial-slides/qconrio-workshop.pdf · Microservices • No limit on size ... • Propagates](https://reader034.vdocuments.net/reader034/viewer/2022050916/5a723b437f8b9abb538d5d35/html5/thumbnails/80.jpg)
When all are complete
root.subscribe( (result) -> asyncResponse.resume(result), (err) -> asyncResponse.resume(err));
![Page 81: Building Microservices with WildFly Swarm - QCon Rioqconrio.com/rio2015/system/files/tutorial-slides/qconrio-workshop.pdf · Microservices • No limit on size ... • Propagates](https://reader034.vdocuments.net/reader034/viewer/2022050916/5a723b437f8b9abb538d5d35/html5/thumbnails/81.jpg)
Let’s Review…
![Page 82: Building Microservices with WildFly Swarm - QCon Rioqconrio.com/rio2015/system/files/tutorial-slides/qconrio-workshop.pdf · Microservices • No limit on size ... • Propagates](https://reader034.vdocuments.net/reader034/viewer/2022050916/5a723b437f8b9abb538d5d35/html5/thumbnails/82.jpg)
Web Client
Keycloak
store pricing
library
![Page 83: Building Microservices with WildFly Swarm - QCon Rioqconrio.com/rio2015/system/files/tutorial-slides/qconrio-workshop.pdf · Microservices • No limit on size ... • Propagates](https://reader034.vdocuments.net/reader034/viewer/2022050916/5a723b437f8b9abb538d5d35/html5/thumbnails/83.jpg)
Review• web-client
• simple .war
• static assets
• RibbonToTheCurbSSEServlet
• store
• simple main(…)
• JAX-RS
• no security
• searchable list of books/authors
• components injected with CDI
• SecureRibbon to pricing
![Page 84: Building Microservices with WildFly Swarm - QCon Rioqconrio.com/rio2015/system/files/tutorial-slides/qconrio-workshop.pdf · Microservices • No limit on size ... • Propagates](https://reader034.vdocuments.net/reader034/viewer/2022050916/5a723b437f8b9abb538d5d35/html5/thumbnails/84.jpg)
Review• pricing
• simple main(…)
• JAX-RS
• optional security
• library
• complex main(…)
• JAX-RS
• required security
• JPA
• CDI
• SecureRibbon to store
![Page 85: Building Microservices with WildFly Swarm - QCon Rioqconrio.com/rio2015/system/files/tutorial-slides/qconrio-workshop.pdf · Microservices • No limit on size ... • Propagates](https://reader034.vdocuments.net/reader034/viewer/2022050916/5a723b437f8b9abb538d5d35/html5/thumbnails/85.jpg)
Logstash
• If you deploy a lot of services, that’s a lot of logs to keep up with
• Logstash + Kibana lets you log to a central location, and search them in aggregate
![Page 86: Building Microservices with WildFly Swarm - QCon Rioqconrio.com/rio2015/system/files/tutorial-slides/qconrio-workshop.pdf · Microservices • No limit on size ... • Propagates](https://reader034.vdocuments.net/reader034/viewer/2022050916/5a723b437f8b9abb538d5d35/html5/thumbnails/86.jpg)
Logstash
• https://download.elastic.co/logstash/logstash/logstash-1.5.3.zip
• https://www.elastic.co/downloads/kibana
![Page 87: Building Microservices with WildFly Swarm - QCon Rioqconrio.com/rio2015/system/files/tutorial-slides/qconrio-workshop.pdf · Microservices • No limit on size ... • Propagates](https://reader034.vdocuments.net/reader034/viewer/2022050916/5a723b437f8b9abb538d5d35/html5/thumbnails/87.jpg)
logstash-wildfly.confinput { tcp { port => 8000 } }
filter { json { source => "message" } }
output { elasticsearch { # Use the embedded elasticsearch for convienence embedded => true protocol => "http" } }
![Page 88: Building Microservices with WildFly Swarm - QCon Rioqconrio.com/rio2015/system/files/tutorial-slides/qconrio-workshop.pdf · Microservices • No limit on size ... • Propagates](https://reader034.vdocuments.net/reader034/viewer/2022050916/5a723b437f8b9abb538d5d35/html5/thumbnails/88.jpg)
./bin/logstash agent -f logstash-wildfly.conf
./bin/kibana
http://localhost:5601
![Page 89: Building Microservices with WildFly Swarm - QCon Rioqconrio.com/rio2015/system/files/tutorial-slides/qconrio-workshop.pdf · Microservices • No limit on size ... • Propagates](https://reader034.vdocuments.net/reader034/viewer/2022050916/5a723b437f8b9abb538d5d35/html5/thumbnails/89.jpg)
Logstash has been configured for all services
this entire time!
![Page 90: Building Microservices with WildFly Swarm - QCon Rioqconrio.com/rio2015/system/files/tutorial-slides/qconrio-workshop.pdf · Microservices • No limit on size ... • Propagates](https://reader034.vdocuments.net/reader034/viewer/2022050916/5a723b437f8b9abb538d5d35/html5/thumbnails/90.jpg)
<!—
<swarm.logstash.hostname>localhost</swarm.logstash.hostname><swarm.logstash.port>8000</swarm.logstash.port>
-->
![Page 91: Building Microservices with WildFly Swarm - QCon Rioqconrio.com/rio2015/system/files/tutorial-slides/qconrio-workshop.pdf · Microservices • No limit on size ... • Propagates](https://reader034.vdocuments.net/reader034/viewer/2022050916/5a723b437f8b9abb538d5d35/html5/thumbnails/91.jpg)
mvn wildfly-swarm:run
![Page 93: Building Microservices with WildFly Swarm - QCon Rioqconrio.com/rio2015/system/files/tutorial-slides/qconrio-workshop.pdf · Microservices • No limit on size ... • Propagates](https://reader034.vdocuments.net/reader034/viewer/2022050916/5a723b437f8b9abb538d5d35/html5/thumbnails/93.jpg)
![Page 94: Building Microservices with WildFly Swarm - QCon Rioqconrio.com/rio2015/system/files/tutorial-slides/qconrio-workshop.pdf · Microservices • No limit on size ... • Propagates](https://reader034.vdocuments.net/reader034/viewer/2022050916/5a723b437f8b9abb538d5d35/html5/thumbnails/94.jpg)
More stuff!
![Page 95: Building Microservices with WildFly Swarm - QCon Rioqconrio.com/rio2015/system/files/tutorial-slides/qconrio-workshop.pdf · Microservices • No limit on size ... • Propagates](https://reader034.vdocuments.net/reader034/viewer/2022050916/5a723b437f8b9abb538d5d35/html5/thumbnails/95.jpg)
wildfly-swarm-maven-plugin
• mvn wildfly-swarm:run
• Just runs your project
• mvn wildfly-swarm:package
• creates the fatjar
![Page 96: Building Microservices with WildFly Swarm - QCon Rioqconrio.com/rio2015/system/files/tutorial-slides/qconrio-workshop.pdf · Microservices • No limit on size ... • Propagates](https://reader034.vdocuments.net/reader034/viewer/2022050916/5a723b437f8b9abb538d5d35/html5/thumbnails/96.jpg)
java -jar booker-store-swarm.jar
![Page 97: Building Microservices with WildFly Swarm - QCon Rioqconrio.com/rio2015/system/files/tutorial-slides/qconrio-workshop.pdf · Microservices • No limit on size ... • Propagates](https://reader034.vdocuments.net/reader034/viewer/2022050916/5a723b437f8b9abb538d5d35/html5/thumbnails/97.jpg)
Arquillian
![Page 98: Building Microservices with WildFly Swarm - QCon Rioqconrio.com/rio2015/system/files/tutorial-slides/qconrio-workshop.pdf · Microservices • No limit on size ... • Propagates](https://reader034.vdocuments.net/reader034/viewer/2022050916/5a723b437f8b9abb538d5d35/html5/thumbnails/98.jpg)
@RunWith(Arquillian.class) public class MyTest { @Deployment public static Archive createDeployment() { . . . create archive } @Test @RunAsClient public void testOutside() { . . . random tests against the deployment }
@Test public void testInside() { . . . can @Inject } }
![Page 99: Building Microservices with WildFly Swarm - QCon Rioqconrio.com/rio2015/system/files/tutorial-slides/qconrio-workshop.pdf · Microservices • No limit on size ... • Propagates](https://reader034.vdocuments.net/reader034/viewer/2022050916/5a723b437f8b9abb538d5d35/html5/thumbnails/99.jpg)
What more would you like to discuss?