Stateless Session for multi-tenant application using Spring Security

Once upon a time, I published one article explaining the principle to build Stateless Session. Coincidentally, we are working on the same task again, but this time, for a multi-tenant application. This time, instead of building the authentication mechanism ourselves, we integrate our solution into Spring Security framework. This article will explain our approach and implementation. Business Requirement We need to build authentication mechanism for an Saas application. Each customer access the application through a dedicated sub-domain. Because the application will be deployed on the cloud, it is pretty obvious that Stateless Session is the preferred choice because it allow us to deploy additional instances without hassle. In the project glossary, each customer is one site. Each application is one app. For example, site may be Microsoft or Google. App may be Gmail, GooglePlus or Google Drive. A sub-domain that user use to access the application will include both app and site. For example, it may looks like microsoft.mail.somedomain.com or google.map.somedomain.com User once login to one app, can access any other apps as long as they are for the same site. Session will be timeout after a certain inactive period. Background Stateless Session Stateless application with timeout is nothing new. Play framework has been stateless from the first release in 2007. We also switched to Stateless Session many years ago. The benefit is pretty clear. Your Load Balancer do not need stickiness; hence, it is easier to configure. As the session in on the browser, we can simply bring in new servers to boost capacity immediately. However, the disadvantage is that your session is not so big and not so confidential anymore. Comparing to stateful application where the session is store in server, stateless application store the session in HTTP cookie, which can not grow more than 4KB. Moreover, as it is cookie, it is recommended that developers only store text or digit on the session rather than complicated data structure. The session is stored in browser and transfer to server in every single request. Therefore, we should keep the session as small as possible and avoid placing any confidential data on it. To put it short, stateless session force developer to change the way application using session. It should be user identity rather than convenient store. Security Framework The idea behind Security Framework is pretty simple, it helps to identify the principle that executing code, checking if he has permission to execute some services and throws exceptions if user does not. In term of implementation, security framework integrate with your service in an AOP style architecture. Every check will be done by the framework before method call. The mechanism for implementing permission check may be filter or proxy. Normally, security framework will store principal information in the thread storage (ThreadLocal in Java). That why it can give developers a static method access to the principal anytime. I think this is somethings developers should know well; otherwise, they may implement permission check or getting principal in some background jobs that running in separate threads. In this situation, it is obviously that the security framework will not be able to find the principal. Single Sign On Single Sign On in mostly implemented using Authentication Server. It is independent of the mechanism to implement session (stateless or stateful). Each application still maintain their own session. On the first access to an application, it will contact authentication server to authenticate user then create its own session. Food for Thought Framework or build from scratch As stateless session is the standard, the biggest concern for us is to use or not to use a security framework. If we use, then Spring Security is the cheapest and fastest solution because we already use Spring Framework in our application. For the benefit, any security framework provide us quick and declarative way to declare assess rule. However, it will not be business logic aware access rule. For example, we can define that only Agent can access the products but we can not define that one agent can only access some products that belong to him. In this situation, we have two choices, building our own business logic permission check from scratch or build 2 layers of permission check, one is only role based, one is business logic aware. After comparing two approaches, we chose the latter one because it is cheaper and faster to build. Our application will function similar to any other Spring Security application. It means that user will be redirected to login page if accessing protected content without session. If the session exist, user will get status code 403. If user access protected content with valid role but unauthorized records, he will get 401 instead. Authentication The next concern is how to integrate our authentication and Authorization mechanism with Spring Security. A standard Spring Security application may process a request like below: The diagram is simplified but still give us a raw idea how things work. If the request is login or logout, the top two filters update the server side session. After that, another filter help check access permission for the request. If the permission check success, another filter will help to store user session to thread storage. After that, controller will execute code with the properly setup environment. For us, we prefer to create our authentication mechanism because the credential need to contain website domain. For example, we may have Joe from Xerox and Joe from WDS accessing Saas application. As Spring Security take control of preparing authentication token and authentication provider, we find it is cheaper to implement login and logout ourselves at the controller level rather than spending effort on customizing Spring Security. As we implement stateless session, there are two works we need to implements here. At first, we need to to construct the session from cookie before any authorization check. We also need to update the session time stamp so that the session is refreshed every time browser send request to server. Because of the earlier decision to do authentication in controller, we face a challenge here. We should not refresh the session before controller executes because we do authentication here. However, some controller methods is attached with the View Resolver that write to output stream immediately. Therefore, we have no chance to refresh cookie after controller being executed. Finally, we choose a slightly compromised solution by using HandlerInterceptorAdapter. This handler interceptor allow us to do extra processing before and after each controller method. We implement refreshing cookie after controller method if the method is for authentication and before controller methods for any other purpose. The new diagram should look like this Cookie To be meaningful, user should have only one session cookie. As the session always change time stamp after each request, we need to update session on every single response. By HTTP protocol, this can only be done if the cookies match name, path and domain. When getting this business requirement, we prefer to try new way of implementing SSO by sharing session cookie. If every application are under the same parent domain and understand the same session cookie, effectively we have a global session. Therefore, there is no need for authentication server any more. To achieve that vision, we must set the domain as the parent domain of all applications. To illustrate this global session, let come back to the earlier example where we have two applications that contain the domain name as microsoft.mail.somedomain.com or google.map.somedomain.com For the session cookie to be global, we will set the domain as somedomain.com. Obviously, the session cookie can be seen and maintained by both applications as long as they share the same secret key to sign. Performance Theoretically, stateless session should be slower. Assuming that the server implementation store session table in memory, passing in JSESSIONID cookie will only trigger a one time read of object from the session table and optional one time write to update last access (for calculating session timeout). In contrast, for stateless session, we need to calculate the hash to validate session cookie, load principal from database, assigning new time stamp and hash again. However, with today server performance, hashing should not add too much delay in server response time. The bigger concern is querying data from database, and for this, we can speed up by using cache. In best case scenario, stateless session can perform closely enough to stateful if there is no DB call made. In stead of loading from session table, which maintained by container, the session is loaded from internal cache, which is maintained by application. In the worst case scenario, requests are being routed to many different servers and the principal object is stored in many instances. This add additional effort to load principal to the cache once per server. While the cost may be high, it occurs only once in a while. If we apply stickiness routing to load balancer, we should be able to achieve best case scenario performance. With this, we can perceive the stateless session cookie as similar mechanism to JSESSIONID but with fall back ability to reconstruct session object. Implementation I have published the sample of this implementation to https://github.com/tuanngda/sgdev-blog repository. Kindly check the stateless-session project. The project requires a mysql database to work. Hence, kindly setup a schema following build.properties or modify the properties file to fit your schema. The project include maven configuration to start up a tomcat server at port 8686. Therefore, you can simply type mvn cargo:run to start up the server. Here is the project hierarchy: I packed both Tomcat 7 server and the database so that it work without any other installation except MySQL. The Tomcat configuration file TOMCAT_HOME/conf/context.xml contain the DataSource declaration and project properties file. Now, let look closer at the implementation Session We need two session objects, one represent the session cookie, one represent the session object that we build internally in Spring security framework: public class SessionCookieData { private int userId; private String appId; private int siteId; private Date timeStamp;} and public class UserSession { private User user; private Site site; public SessionCookieData generateSessionCookieData(){  return new SessionCookieData(user.getId(), user.getAppId(), site.getId()); }} With this combo, we have the objects to store session object in cookie and memory. The next step is to implement a method that allow us to build session object from cookie data. public interface UserSessionService { public UserSession getUserSession(SessionCookieData sessionData);} Now, one more service to retrieve and generate cookie from cookie data. public class SessionCookieService { public Cookie generateSessionCookie(SessionCookieData cookieData, String domain); public SessionCookieData getSessionCookieData(Cookie sessionCookie); public Cookie generateSignCookie(Cookie sessionCookie);} Up to this point, We have the service that help us to do the conversion Cookie --> SessionCookieData --> UserSession and Session --> SessionCookieData --> Cookie Now, we should have enough material to integrate stateless session with Spring Security framework Integrate with Spring security At first, we need to add a filter to construct session from cookie. Because this should happen before permission check, it is better to use AbstractPreAuthenticatedProcessingFilter @Component(value="cookieSessionFilter")public class CookieSessionFilter extends AbstractPreAuthenticatedProcessingFilter { ... @Override protected Object getPreAuthenticatedPrincipal(HttpServletRequest request) {  SecurityContext securityContext = extractSecurityContext(request);    if (securityContext.getAuthentication()!=null       && securityContext.getAuthentication().isAuthenticated()){   UserAuthentication userAuthentication = (UserAuthentication) securityContext.getAuthentication();   UserSession session = (UserSession) userAuthentication.getDetails();   SecurityContextHolder.setContext(securityContext);   return session;  }    return new UserSession(); } ... } The filter above construct principal object from session cookie. The filter also create a PreAuthenticatedAuthenticationToken that will be used later for authentication. It is obviously that Spring will not understand this Principal. Therefore, we need to provide our own AuthenticationProvider that manage to authenticate user based on this principal. public class UserAuthenticationProvider implements AuthenticationProvider {@Override  public Authentication authenticate(Authentication authentication) throws AuthenticationException {    PreAuthenticatedAuthenticationToken token = (PreAuthenticatedAuthenticationToken) authentication;    UserSession session = (UserSession)token.getPrincipal();    if (session != null && session.getUser() != null){      SecurityContext securityContext = SecurityContextHolder.getContext();      securityContext.setAuthentication(new UserAuthentication(session));      return new UserAuthentication(session);    }    throw new BadCredentialsException("Unknown user name or password");  }} This is Spring way. User is authenticated if we manage to provide a valid Authentication object. Practically, we let user login by session cookie for every single request. However, there are times that we need to alter user session and we can do it as usual in controller method. We simply overwrite the SecurityContext, which is setup earlier in the pre-authentication filter. public ModelAndView login(String login, String password, String siteCode) throws IOException{        if(StringUtils.isEmpty(login) || StringUtils.isEmpty(password)){      throw new HttpServerErrorException(HttpStatus.BAD_REQUEST, "Missing login and password");    }        User user = authService.login(siteCode, login, password);    if(user!=null){      SecurityContext securityContext = SecurityContextHolder.getContext();      UserSession userSession = new UserSession();      userSession.setSite(user.getSite());      userSession.setUser(user);      securityContext.setAuthentication(new UserAuthentication(userSession));    }else{      throw new HttpServerErrorException(HttpStatus.UNAUTHORIZED, "Invalid login or password");    }        return new ModelAndView(new MappingJackson2JsonView());      } Refresh Session Up to now, you may notice that we have never mentioned the writing of cookie. Provided that we have a valid Authentication object and our SecurityContext contain the UserSession, it is important that we need to send this information back to browser. Before the HttpServletResponse is generated, we must generate and attach the session cookie to it. This new session cookie,  which has similar domain and path will replace the older session cookie that the browser is keeping. As discussed above, refreshing session is better to be done after controller method because we implement authentication at this layer. However, there is a challenge caused by ViewResolver of Spring MVC. Sometimes, it writes to OutputStream so soon that any attempt to add cookie to response will be useless. After consideration, we come up with a compromise solution that refresh session before controller methods for normal requests and after controller methods for authentication requests. To know whether requests is for authentication, we place an newly defined annotation at the authentication methods.   @Override  public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {    if (handler instanceof HandlerMethod){      HandlerMethod handlerMethod = (HandlerMethod) handler;      SessionUpdate sessionUpdateAnnotation = handlerMethod.getMethod().getAnnotation(SessionUpdate.class);            if (sessionUpdateAnnotation == null){        SecurityContext context = SecurityContextHolder.getContext();        if (context.getAuthentication() instanceof UserAuthentication){          UserAuthentication userAuthentication = (UserAuthentication)context.getAuthentication();          UserSession session = (UserSession) userAuthentication.getDetails();          persistSessionCookie(response, session);        }      }    }    return true;  }  @Override  public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,      ModelAndView modelAndView) throws Exception {    if (handler instanceof HandlerMethod){      HandlerMethod handlerMethod = (HandlerMethod) handler;      SessionUpdate sessionUpdateAnnotation = handlerMethod.getMethod().getAnnotation(SessionUpdate.class);            if (sessionUpdateAnnotation != null){        SecurityContext context = SecurityContextHolder.getContext();        if (context.getAuthentication() instanceof UserAuthentication){          UserAuthentication userAuthentication = (UserAuthentication)context.getAuthentication();          UserSession session = (UserSession) userAuthentication.getDetails();          persistSessionCookie(response, session);        }      }    }  } Conclusion The solution works well for us but we do not have the confident that this is the best practices possible. However, it is simple and does not cost us much effort to implement (around 3 days include testing). Kindly feedback if you have any better idea to build stateless session with Spring.

Posted by on 7 September 2014 | 10:31 pm

What is the next step in the process for JSF and MVC?

Now that both JSRs have been filed what is the next step? Well, we are waiting for the ballots to be done. Once the ballots are done and the results are in (and assuming they are positive, which I assume they will be), then the next part in the process is to form the EG and get started for real. For both JSRs the approval ballot needs to be done September 22nd, 2014. So stay tuned! Enjoy!

Posted by on 4 September 2014 | 3:53 pm

Load Balance WebSockets using Apache HTTPD (Tech Tip #48)

JBoss EAP 6.3 provides a technology preview of WebSocket and WildFly have supported them as part of Java EE 7 compliance. github.com/javaee-samples/javaee7-samples/tree/master/websocket provide tons of Java EE 7 samples that run on WildFly. If you are interested in similar functionality on JBoss EAP 6.3 then github.com/jboss-developer/jboss-eap-quickstarts/tree/6.4.x-develop/websocket-hello is a quickstart. In addition, there are a few more samples at github.com/arun-gupta/jboss-samples/tree/master/eap63. One of the common questions asked related to WebSockets is how to how to load balance  them. This Tech Tip will explain that for WildFly and JBoss EAP 6.3. First, what are the main components ? At least Apache HTTPD 2.4.5 is required. Now HTTPD binaries are not available for Mac but fortunately compiling instructions are explained clearly in Tech Tip #45. mod_proxy_wstunnel is an Apache module that provides support for tunneling of Web Socket connections to a backend Web Sockets server, such as WildFly or JBoss EAP. It is a support module to mod_proxy that provide support for a number of popular protocols as well as several different load balancing algorithms. The connection is automagically upgraded to a WebSocket connection.  And all the modules are already included in the modules directory. mod_proxy_balancer module is required that provides load balancing for HTTP and other protocols. Let's go! Download and unzip WildFly 8.1. Start WildFly 8.1 in domain mode using ./bin/domain.sh. Download this chat sample, rename the file to "chat.war" and deploy to "main-server-group" as: ~/tools/wildfly-8.1.0.Final/bin/jboss-cli.sh -c --command="deploy chat.war --server-groups=main-server-group" The only difference from the original Java EE 7 WebSocket Chat sample is the addition of System.getProperty("jboss.node.name") to display the name of WildFly instance serving the application. The source code is available at github.com/arun-gupta/wildfly-samples/tree/master/websocket-loadbalance. Uncomment the following lines in /usr/local/apache2/conf/httpd.conf: LoadModule lbmethod_byrequests_module modules/mod_lbmethod_byrequests.soLoadModule proxy_module modules/mod_proxy.soLoadModule proxy_wstunnel_module modules/mod_proxy_wstunnel.soLoadModule proxy_balancer_module modules/mod_proxy_balancer.so This will enable all the required modules. Add the following code fragment at the end of "httpd.conf": <Proxy balancer://mycluster>    BalancerMember ws://localhost:8080    BalancerMember ws://localhost:8230</Proxy>ProxyPass /chat balancer://mycluster/chat Proxy is a container for proxied resources and is creating a load balancing group in this case using balancer directive. BalancerMember adds a member to this load balancing group.  ProxyPass is a standard directive that maps remote servers running on different ports into the space of the local server. In this case, WildFly is started in domain mode and so starts two instances on port 8080 and 8230. Both of these instances are mapped to localhost:80, which is where Apache HTTPD is running by default. The deployed chat sample is now accessible at localhost:8080/chat (first instance in the managed domain), localhost:8230/chat (second WildFly instance in the managed domain), and localhost/chat (via Apache HTTPD). Now even if you kill one of the WildFly instances, the other instance will continue to serve the client. Note, this only gives application availability as there is no session failover in this. This was also verified on JBoss EAP 6.3 and there are a few differences: Use the sample from github.com/arun-gupta/jboss-samples/tree/master/eap63/websocket-chat instead. The generated archive name is different and so the command would look slightly different too: ~/tools/jboss-eap-6.3/bin/jboss-cli.sh -c --command="deploy websocket-chat-1.0-SNAPSHOT.war --server-groups=main-server-group" Configure "httpd.conf" as: <Proxy balancer://mycluster>    BalancerMember ws://localhost:8080    BalancerMember ws://localhost:8230</Proxy>ProxyPass /websocket-chat-1.0-SNAPSHOT balancer://mycluster/websocket-chat-1.0-SNAPSHOT And that's it! Watch this live in action: An important point to understand is that there is no concept of "sticky sessions" in WebSocket as, unlike HTTP, there is a direct and "permanent" connection between the client and the server in this case. Enjoy!

Posted by on 29 August 2014 | 11:28 am

WildFly with a custom configuration in OpenShift (Tech Tip #47)

WildFly instances can be easily started in OpenShift. Tech Tip #7 shows how to spin up an instance of WildFly in OpenShift. Tech Tip #21 explained how to get started using JBoss Tools. Now this WildFly instance is started with the stock configuration.xml. However some times you may want to configure the containers or specify additional configuration information in this file. This Tech Tip will show you how to do that. Let's go! Start a WildFly instance as explained in Tech Tip #7. On the application page, clone the workspace associated with this application. The command will look something like: git clone ssh://XXXXXXXXXX@test-milestogo.rhcloud.com/~/git/test.git/ This workspace has .openshift/standalone.xml file. Edit this file to meet your need. For example, if you want to use Infinispan as a persistency solution in standalone mode, then you'll add the following code fragment: [prettify]&lt;cache-container name="myCache" default-cache="cachedb"&gt;     &lt;local-cache name="cachedb"/&gt; &lt;/cache-container&gt;[/prettify] under <subsystem xmlns="urn:jboss:domain:infinispan:2.0"> section. Commit and push the change: config> git commit standalone.xml -m"additional configuration elements"[master cef567d] additional configuration elements 1 file changed, 1 deletion(-)config> git push This will automatically restart the cartridge and show the output as: Counting objects: 9, done.Delta compression using up to 8 threads.Compressing objects: 100% (5/5), done.Writing objects: 100% (5/5), 656 bytes | 0 bytes/s, done.Total 5 (delta 1), reused 0 (delta 0)remote: Stopping wildfly cartremote: Repairing links for 1 deploymentsremote: Building git ref 'master', commit cef567dremote: Found pom.xml... attempting to build with 'mvn -e clean package -Popenshift -DskipTests'remote: Apache Maven 3.0.4 (r1232336; 2012-12-18 14:36:37-0500)remote: Maven home: /usr/share/java/apache-maven-3.0.4remote: Java version: 1.8.0_05, vendor: Oracle Corporationremote: Java home: /var/lib/openshift/XXXXXXXXXX/wildfly/usr/lib/jvm/jdk1.8.0_05/jreremote: Default locale: en_US, platform encoding: ANSI_X3.4-1968remote: OS name: "linux", version: "2.6.32-431.23.3.el6.x86_64", arch: "i386", family: "unix"remote: [INFO] Scanning for projects...remote: [INFO]                                                                         remote: [INFO] ------------------------------------------------------------------------remote: [INFO] Building test 1.0remote: [INFO] ------------------------------------------------------------------------remote: [INFO] remote: [INFO] --- maven-clean-plugin:2.4.1:clean (default-clean) @ test ---remote: [INFO] remote: [INFO] --- maven-resources-plugin:2.5:resources (default-resources) @ test ---remote: [debug] execute contextualizeremote: [INFO] Using 'UTF-8' encoding to copy filtered resources.remote: [INFO] Copying 1 resourceremote: [INFO] remote: [INFO] --- maven-compiler-plugin:2.3.2:compile (default-compile) @ test ---remote: [INFO] Nothing to compile - all classes are up to dateremote: [INFO] remote: [INFO] --- maven-resources-plugin:2.5:testResources (default-testResources) @ test ---remote: [debug] execute contextualizeremote: [INFO] Using 'UTF-8' encoding to copy filtered resources.remote: [INFO] skip non existing resourceDirectory /var/lib/openshift/XXXXXXXXXX/app-root/runtime/repo/src/test/resourcesremote: [INFO] remote: [INFO] --- maven-compiler-plugin:2.3.2:testCompile (default-testCompile) @ test ---remote: [INFO] No sources to compileremote: [INFO] remote: [INFO] --- maven-surefire-plugin:2.10:test (default-test) @ test ---remote: [INFO] Tests are skipped.remote: [INFO] remote: [INFO] --- maven-war-plugin:2.3:war (default-war) @ test ---remote: [INFO] Packaging webappremote: [INFO] Assembling webapp [test] in [/var/lib/openshift/XXXXXXXXXX/app-root/runtime/repo/target/test]remote: [INFO] Processing war projectremote: [INFO] Copying webapp resources [/var/lib/openshift/XXXXXXXXXX/app-root/runtime/repo/src/main/webapp]remote: [INFO] Webapp assembled in [341 msecs]remote: [INFO] Building war: /var/lib/openshift/XXXXXXXXXX/app-root/runtime/repo/deployments/ROOT.warremote: [INFO] ------------------------------------------------------------------------remote: [INFO] BUILD SUCCESSremote: [INFO] ------------------------------------------------------------------------remote: [INFO] Total time: 8.365sremote: [INFO] Finished at: Tue Aug 26 18:01:19 EDT 2014remote: [INFO] Final Memory: 9M/113Mremote: [INFO] ------------------------------------------------------------------------remote: Preparing build for deploymentremote: Deployment id is 336d5b75remote: Activating deploymentremote: Deploying WildFlyremote: Starting wildfly cartremote: Found 127.12.40.129:8080 listening portremote: Found 127.12.40.129:9990 listening portremote: /var/lib/openshift/XXXXXXXXXX/wildfly/standalone/deployments /var/lib/openshift/XXXXXXXXXX/wildflyremote: /var/lib/openshift/XXXXXXXXXX/wildflyremote: CLIENT_MESSAGE: Artifacts deployed: ./ROOT.warremote: -------------------------remote: Git Post-Receive Result: successremote: Activation status: successremote: Deployment completed with status: successTo ssh://XXXXXXXXXX@test-milestogo.rhcloud.com/~/git/test.git/   b08ebff..cef567d  master -> master Now the WildFly instance in OpenShift will use the updated configuration file. You can even verify this by logging into your application as: ssh XXXXXXXXXX@test-milestogo.rhcloud.com And checking for the updated elements in wildfly/standalone/configuration/standalone.xml file. Alternatively, you can ssh into your instance and use the JBoss CLI to make updates to your standalone.xml file. Enjoy!

Posted by on 29 August 2014 | 11:28 am

Java EE 7 Real World Experience: Campground Management with Tipi.camp

Tipi.camp provides a simple campground management software and targets 25,000+ independent campgrounds all over Europe. It provides a customer-friendly booking-portal and a RESTful API for partners to integrate. The project was conceived in September 2013 when Christoph returned from vacation, disappointed because of the missed booking for their tent. And now he has created a new solution connecting campers and campgrounds with each other. The website offers a SaaS where campgrounds can register their camp sites and campers can look at the availability of these campgrounds, check out their calendar, pick a site and make a reservation. It is also available for on-site installation if you prefer running it on your domain. Think of it as koa.com, but available to all the independent campgrounds and much more modern ;) The landing page is certainly very fancy: Websites of smaller campgrounds are typically characterized by low data maintenance and absence of a booking possibility. tipi.camp has advantages: Easy-to-use portal for campground owners and campers Campground owner administrate and book his sites independently Customer data management External sales channels, for example booking.com, can be connected to sell the log cabins RESTful API it is also possible to handle larger individual installations Campgrounds get their own portal, reservations, channel management, email and much more for €1/day if they are located in Europe or $1/day if they are in US. Each campground with an Internet connection and browser (whether computer or iPad) can use the software. In terms of the overall flow, campground owner register their campground with tipi.camp. Traveler checks out the calendar and books the campground using the responsive portal.   Check out the welcome page: Campers can search through the available camps and then look at the calendar of a particular camp: Pick a particular site on the campground: And then checkout to make the payment: This website is built using Java EE 7:   Here is a brief description of the technology stack: Presentation JavaServer Faces + Expression Language. Different templates are used for desktop and iPad apps. JSF Template Library might be used to provide a fully customized portal for the campground owners later. Security: JAAS Principal + JDBC realm Bean discovery mode="all" Middle Tier EJB for business boundaries Servlets with JSON for web hooks: response from Paypal and Sendgrid JAX-RS for exposing API to partners Backend JPA + Bean Validation, use @Index for database generation during development. Flyway API for database migrations in production. Concurrency: Calculation of statistics and sending messages, Sendgrid takes ~1-4 seconds to send messages Using @Startup @Singleton @Schedule to run a job at pre-defined time Technologies from outside the platform were: Primefaces 5 for the GUI and Bootstrap for the responsive Enduser-Portal. Sendgrid API for sending mails. This is required as opposed to JavaMail because specific meta information needs to be added to each email. Misc apache commons (eq. FileUtils.writeByteArrayToFile or IOUtils.toByteArray) - there are only a few sections. Flyway API for database migrations Junit with Derby – for testing Toolset JDK 8 IntelliJ 13.1 with Maven Wildfly 8.1.0.Final - Single instance of WildFly is used. The app was previously deployed on GlassFish. Apache httpd is used to: performance-tuning with KeepAlive, mod_expires for the images and the compression easy SSL configuration handle more WildFly under 1 hostname with the mod_proxy mod_redirect for redirect all http requests to the app to https Github Jenkins loader.io for Load-Testing Currently the application is deployed on a self-hostet Linux-Server in the hetzner.de data center. Wish list for Java EE 8 Most used Apache Commons Libs @Temporal works with LocalDate and LocalDateTime Batch processing API does support generics And here are supporting quotes on Java EE 7 the technology is perfect. very productive with java/ee7, i’m and our customers are very happy with java ee7. With the technology, really everything is possible. And on WildFly: superb, unique product So, do you want to start on this terrific two combination of Java EE 7 + WildFly ? Download WildFly 8.1 today, learn the technology by reading/trying Java EE 7 samples, browse through Java EE 7 resources. Or if you want to be on the bleeding edge, check out WildFly 9.0. Many thanks to Christoph Gapp (info@tipi.camp) and Adam Bien (@adambien) for providing all the answers! Are you using Java EE 7 and WildFly to deploy your projects ? Would love to feature you here! Send me an email or leave a comment on the blog.  

Posted by on 29 August 2014 | 11:27 am

Cloud in a Box: OpenShift Online in VirtualBox (Tech Tip #46)

OpenShift is Red Hat's PaaS platform and comes in three flavors: Origin is the Community PaaS offering. You can explore the community-driven open source upstream of OpenShift. Join the community. Online is the Public PaaS offering. Host your applications in the public cloud with automated provisioning, management, and scaling of applications. Sign up for free. Enterprise is the Private PaaS offering. Leverage PaaS in your own data centers and private cloud. Request evaluation. This Tech Tip will show how you can setup a Virtual VM running with OpenShift Online. Instructions at openshift.github.io/documentation/oo_deployment_guide_vm.html are pretty self explanatory. Here are the exact ones that I followed on Mavericks: Download VM: curl -O https://mirror.openshift.com/pub/origin-server/release/4/images/openshift-origin.tgz Unpack VM files tar xzvf ~/Downloads/openshift-origin.tgz x OpenShift Origin v4/x OpenShift Origin v4/OpenShift Origin v4.nvramx OpenShift Origin v4/OpenShift Origin v4.vboxx OpenShift Origin v4/OpenShift Origin v4.vmsdx OpenShift Origin v4/OpenShift Origin v4.vmxx OpenShift Origin v4/OpenShift Origin v4.vmxfx OpenShift Origin v4/._origin-vm.vmdkx OpenShift Origin v4/origin-vm.vmdk Follow the instructions to create a VirtualBox instance. Create a new hard drive using the unzipped origin-vm.vmdk file. IMPORTANT: Instead of 4.2.4 to add bridged networking, setup a host-only network using 4.2.5. Boot the VM to see the output as: Type "5" to exit to the command prompt. VM comes pre-configured with Avahi DNS service and so now you can access OpenShift console at broker.openshift.local and seen as: The username/password are "demo"/"changeme". Create an SSH tunnel into the VM as: ssh -f root@broker.openshift.local -L 8080:localhost:8080 -N Password is "changeme". OpenShift admin console is now accessible at localhost:8080/admin-console and looks like: More details about Admin Console are well documented. Many thanks to Harrison for guiding me through creating this process! Ask your OpenShift questions at stackoverflow or follow them at @openshift. Enjoy!  

Posted by on 29 August 2014 | 11:27 am

Compiling Apache HTTPD on Mac (Tech Tip #45)

One of my blogs needed Apache HTTPD 2.4.x on Mac but quickly realized that the binaries are available only for Netware and Win32. Even the build instructions were only for RPM-based systems. So I downloaded the source code and started building it. Complete compile instructions are explained here. However there were some issues on Mavericks and so decided to document it. Let's go! Download the source bundle and unzip: tar xzvf ~/Downloads/httpd-2.4.10.tar.bz2 Source code comes with INSTALL instructions and per that the following should've worked: ./configure --prefix=PREFIXmakemake installPREFIX/bin/apachectl start So gave the command ./configure --prefix=/usr/local/apache2 and got the first error: httpd-2.4.10> ./configure --prefix=/usr/local/apache2checking for chosen layout... Apachechecking for working mkdir -p... yeschecking for grep that handles long lines and -e... /usr/bin/grepchecking for egrep... /usr/bin/grep -Echecking build system type... x86_64-apple-darwin13.3.0checking host system type... x86_64-apple-darwin13.3.0checking target system type... x86_64-apple-darwin13.3.0configure: configure: Configuring Apache Portable Runtime library...configure: checking for APR... yes  setting CC to "/Applications/Xcode.app/Contents/Developer/Toolchains/OSX10.9.xctoolchain/usr/bin/cc"  setting CPP to "/Applications/Xcode.app/Contents/Developer/Toolchains/OSX10.9.xctoolchain/usr/bin/cc -E"  setting CFLAGS to " "  setting CPPFLAGS to " -DDARWIN -DSIGPROCMASK_SETS_THREAD_MASK"  setting LDFLAGS to " "configure: configure: Configuring Apache Portable Runtime Utility library...configure: checking for APR-util... yeschecking for gcc... /Applications/Xcode.app/Contents/Developer/Toolchains/OSX10.9.xctoolchain/usr/bin/ccchecking whether the C compiler works... noconfigure: error: in `/Users/arungupta/workspaces/httpd-2.4.10':configure: error: C compiler cannot create executablesSee `config.log' for more details Moved past "checking whether the C compiler works... no" error by following instructions on stackoverflow #13587001.In short, do the following for Mavericks sudo ln -s /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain /Applications/Xcode.app/Contents/Developer/Toolchains/OSX10.9.xctoolchain Issued the command to compile the server again and got the error as shown: httpd-2.4.10> ./configure --prefix=/usr/local/apache2 checking for chosen layout... Apachechecking for working mkdir -p... yeschecking for grep that handles long lines and -e... /usr/bin/grepchecking for egrep... /usr/bin/grep -Echecking build system type... x86_64-apple-darwin13.3.0checking host system type... x86_64-apple-darwin13.3.0checking target system type... x86_64-apple-darwin13.3.0configure: configure: Configuring Apache Portable Runtime library...configure: checking for APR... yes  setting CC to "/Applications/Xcode.app/Contents/Developer/Toolchains/OSX10.9.xctoolchain/usr/bin/cc"  setting CPP to "/Applications/Xcode.app/Contents/Developer/Toolchains/OSX10.9.xctoolchain/usr/bin/cc -E"  setting CFLAGS to " "  setting CPPFLAGS to " -DDARWIN -DSIGPROCMASK_SETS_THREAD_MASK"  setting LDFLAGS to " "configure: configure: Configuring Apache Portable Runtime Utility library...configure: checking for APR-util... yeschecking for gcc... /Applications/Xcode.app/Contents/Developer/Toolchains/OSX10.9.xctoolchain/usr/bin/ccchecking whether the C compiler works... yeschecking for C compiler default output file name... a.outchecking for suffix of executables... checking whether we are cross compiling... nochecking for suffix of object files... ochecking whether we are using the GNU C compiler... yeschecking whether /Applications/Xcode.app/Contents/Developer/Toolchains/OSX10.9.xctoolchain/usr/bin/cc accepts -g... yeschecking for /Applications/Xcode.app/Contents/Developer/Toolchains/OSX10.9.xctoolchain/usr/bin/cc option to accept ISO C89... none neededchecking how to run the C preprocessor... /Applications/Xcode.app/Contents/Developer/Toolchains/OSX10.9.xctoolchain/usr/bin/cc -Echecking for /Applications/Xcode.app/Contents/Developer/Toolchains/OSX10.9.xctoolchain/usr/bin/cc option to accept ISO C99... none neededchecking for pcre-config... falseconfigure: error: pcre-config for libpcre not found. PCRE is required and available from http://pcre.org/ This was resolved using stackoverflow #10663180. In short: Download PCRE as: curl -O ftp://ftp.csx.cam.ac.uk/pub/software/programming/pcre/pcre-8.33.zip Compile and install as: ./configure --prefix=/usr/local/pcremakesudo make install The compilation output is shown here. Compile HTTPD source again as: httpd-2.4.10> ./configure --prefix=/usr/local/apache2 --with-pcre=/usr/local/pcrechecking for chosen layout... Apachechecking for working mkdir -p... yeschecking for grep that handles long lines and -e... /usr/bin/grepchecking for egrep... /usr/bin/grep -Echecking build system type... x86_64-apple-darwin13.3.0checking host system type... x86_64-apple-darwin13.3.0checking target system type... x86_64-apple-darwin13.3.0configure: . . .creating server/Makefilecreating support/Makefilecreating test/Makefileconfig.status: creating docs/conf/httpd.confconfig.status: creating docs/conf/extra/httpd-autoindex.confconfig.status: creating docs/conf/extra/httpd-dav.confconfig.status: creating docs/conf/extra/httpd-default.confconfig.status: creating docs/conf/extra/httpd-info.confconfig.status: creating docs/conf/extra/httpd-languages.confconfig.status: creating docs/conf/extra/httpd-manual.confconfig.status: creating docs/conf/extra/httpd-mpm.confconfig.status: creating docs/conf/extra/httpd-multilang-errordoc.confconfig.status: creating docs/conf/extra/httpd-ssl.confconfig.status: creating docs/conf/extra/httpd-userdir.confconfig.status: creating docs/conf/extra/httpd-vhosts.confconfig.status: creating docs/conf/extra/proxy-html.confconfig.status: creating include/ap_config_layout.hconfig.status: creating support/apxsconfig.status: creating support/apachectlconfig.status: creating support/dbmmanageconfig.status: creating support/envvars-stdconfig.status: creating support/log_server_statusconfig.status: creating support/logresolve.plconfig.status: creating support/phf_abuse_log.cgiconfig.status: creating support/split-logfileconfig.status: creating build/rules.mkconfig.status: creating build/pkg/pkginfoconfig.status: creating build/config_vars.shconfig.status: creating include/ap_config_auto.hconfig.status: executing default commands Complete output of this configuration is here. Now issue the command make: httpd-2.4.10> makeMaking all in srclibMaking all in osMaking all in unix/usr/share/apr-1/build-1/libtool --silent --mode=compile /Applications/Xcode.app/Contents/Developer/Toolchains/OSX10.9.xctoolchain/usr/bin/cc        -DDARWIN -DSIGPROCMASK_SETS_THREAD_MASK     -I. -I/Users/arungupta/workspaces/httpd-2.4.10/os/unix -I/Users/arungupta/workspaces/httpd-2.4.10/include -I/usr/include/apr-1 -I/usr/local/pcre/include -I/Users/arungupta/workspaces/httpd-2.4.10/modules/aaa -I/Users/arungupta/workspaces/httpd-2.4.10/modules/cache -I/Users/arungupta/workspaces/httpd-2.4.10/modules/core -I/Users/arungupta/workspaces/httpd-2.4.10/modules/database -I/Users/arungupta/workspaces/httpd-2.4.10/modules/filters -I/Users/arungupta/workspaces/httpd-2.4.10/modules/ldap -I/Users/arungupta/workspaces/httpd-2.4.10/modules/loggers -I/Users/arungupta/workspaces/httpd-2.4.10/modules/lua -I/Users/arungupta/workspaces/httpd-2.4.10/modules/proxy -I/Users/arungupta/workspaces/httpd-2.4.10/modules/session -I/Users/arungupta/workspaces/httpd-2.4.10/modules/ssl -I/Users/arungupta/workspaces/httpd-2.4.10/modules/test -I/Users/arungupta/workspaces/httpd-2.4.10/server -I/Users/arungupta/workspaces/httpd-2.4.10/modules/arch/unix -I/Users/arungupta/workspaces/httpd-2.4.10/modules/dav/main -I/Users/arungupta/workspaces/httpd-2.4.10/modules/generators -I/Users/arungupta/workspaces/httpd-2.4.10/modules/mappers  -prefer-non-pic -static -c unixd.c && touch unixd.lo/usr/share/apr-1/build-1/libtool --silent --mode=link /Applications/Xcode.app/Contents/Developer/Toolchains/OSX10.9.xctoolchain/usr/bin/cc           -o libos.la -static  unixd.lo  Making all in serverMaking all in mpmMaking all in worker. . .warning: no debug symbols in executable (-arch x86_64)/usr/share/apr-1/build-1/libtool --silent --mode=compile /Applications/Xcode.app/Contents/Developer/Toolchains/OSX10.9.xctoolchain/usr/bin/cc        -DDARWIN -DSIGPROCMASK_SETS_THREAD_MASK     -I. -I/Users/arungupta/workspaces/httpd-2.4.10/os/unix -I/Users/arungupta/workspaces/httpd-2.4.10/include -I/usr/include/apr-1 -I/usr/local/pcre/include -I/Users/arungupta/workspaces/httpd-2.4.10/modules/aaa -I/Users/arungupta/workspaces/httpd-2.4.10/modules/cache -I/Users/arungupta/workspaces/httpd-2.4.10/modules/core -I/Users/arungupta/workspaces/httpd-2.4.10/modules/database -I/Users/arungupta/workspaces/httpd-2.4.10/modules/filters -I/Users/arungupta/workspaces/httpd-2.4.10/modules/ldap -I/Users/arungupta/workspaces/httpd-2.4.10/modules/loggers -I/Users/arungupta/workspaces/httpd-2.4.10/modules/lua -I/Users/arungupta/workspaces/httpd-2.4.10/modules/proxy -I/Users/arungupta/workspaces/httpd-2.4.10/modules/session -I/Users/arungupta/workspaces/httpd-2.4.10/modules/ssl -I/Users/arungupta/workspaces/httpd-2.4.10/modules/test -I/Users/arungupta/workspaces/httpd-2.4.10/server -I/Users/arungupta/workspaces/httpd-2.4.10/modules/arch/unix -I/Users/arungupta/workspaces/httpd-2.4.10/modules/dav/main -I/Users/arungupta/workspaces/httpd-2.4.10/modules/generators -I/Users/arungupta/workspaces/httpd-2.4.10/modules/mappers -prefer-pic -c mod_rewrite.c && touch mod_rewrite.slo/usr/share/apr-1/build-1/libtool --silent --mode=link /Applications/Xcode.app/Contents/Developer/Toolchains/OSX10.9.xctoolchain/usr/bin/cc             -o mod_rewrite.la -rpath /usr/local/apache2/modules -module -avoid-version  mod_rewrite.lo warning: no debug symbols in executable (-arch x86_64) Complete output of the command is shown here. Finally install Apache2 as: httpd-2.4.10> sudo make installPassword:Making install in srclibMaking install in osMaking install in unixMaking install in serverMaking install in mpmMaking install in workermkdir /usr/local/apache2mkdir /usr/local/apache2/modulesMaking install in modules. . .Installing man pages and online manualmkdir /usr/local/apache2/manmkdir /usr/local/apache2/man/man1mkdir /usr/local/apache2/man/man8mkdir /usr/local/apache2/manual Complete output of this command is shown here. Version for HTTPD can be checked as: httpd-2.4.10> /usr/local/apache2/bin/httpd -vServer version: Apache/2.4.10 (Unix)Server built:   Aug 22 2014 16:00:19 Server can be started as: sudo /usr/local/apache2/bin/apachectl start Stopped as: sudo /usr/local/apache2/bin/apachectl stop Restarted as: sudo /usr/local/apache2/bin/apachectl restart Enjoy!

Posted by on 29 August 2014 | 11:26 am

WildFly 9: Features and Getting Started (Tech Tip #43)

WildFly 8.1 provides a Java EE 7 compliant application server, and is pretty awesome! WildFly team has been actively working this summer on the next release. WildFly 9 features were announced a few weeks ago. Here is a quick summary and links to discussions on wildfly-dev: Core/Servlet/Full Split Graceful shutdown Elytron (Security improvments) Switching to the JDK ORB from JacORB Undertow as a mod_cluster frontend Subsystem Capabilities and Requirements EAP 6.4 RFEs (TBA) Links/details to rest of the features TBD. So how do you get started with WildFly 9 ? Building WildFly 9 requires at least have Maven 3.2.1, download the latest here. Clone the workspace as: git clone https://github.com/wildfly/wildfly.git Build the workspace as: mvn install -DskipTests Took 02:36 mins to build on my machine :) Unzip dist/target/wildfly-9.0.0.Alpha1-SNAPSHOT.zip to a new directory Run WildFly as: wildfly-9.0.0.Alpha1-SNAPSHOT> ./bin/standalone.sh =========================================================================  JBoss Bootstrap Environment  JBOSS_HOME: /Users/arungupta/tools/wildfly-9.0.0.Alpha1-SNAPSHOT  JAVA: /Library/Java/JavaVirtualMachines/jdk1.8.0_20.jdk/Contents/Home/bin/java  JAVA_OPTS:  -server -XX:+UseCompressedOops  -server -XX:+UseCompressedOops -Xms64m -Xmx512m -XX:MaxPermSize=256m -Djava.net.preferIPv4Stack=true -Djboss.modules.system.pkgs=org.jboss.byteman -Djava.awt.headless=true=========================================================================Java HotSpot(TM) 64-Bit Server VM warning: ignoring option MaxPermSize=256m; support was removed in 8.014:58:52,501 INFO  [org.jboss.modules] (main) JBoss Modules version 1.3.4.Final14:58:53,043 INFO  [org.jboss.msc] (main) JBoss MSC version 1.2.2.Final14:58:53,122 INFO  [org.jboss.as] (MSC service thread 1-6) WFLYSRV0049: WildFly 1.0.0.Alpha5 "Kenny" starting14:58:53,941 INFO  [org.jboss.as.server] (Controller Boot Thread) WFLYSRV0039: Creating http management service using socket-binding (management-http)14:58:53,957 INFO  [org.xnio] (MSC service thread 1-11) XNIO version 3.3.0.Beta114:58:53,963 INFO  [org.xnio.nio] (MSC service thread 1-11) XNIO NIO Implementation Version 3.3.0.Beta114:58:53,986 INFO  [org.jboss.as.security] (ServerService Thread Pool -- 49) WFLYSEC0002: Activating Security Subsystem14:58:53,986 WARN  [org.jboss.as.txn] (ServerService Thread Pool -- 50) WFLYTX0013: Node identifier property is set to the default value. Please make sure it is unique.14:58:54,000 INFO  [org.jboss.as.webservices] (ServerService Thread Pool -- 52) WFLYWS0002: Activating WebServices Extension14:58:54,000 INFO  [org.jboss.as.security] (MSC service thread 1-15) WFLYSEC0001: Current PicketBox version=4.0.21.Beta314:58:54,000 INFO  [org.jboss.as.clustering.infinispan] (ServerService Thread Pool -- 35) WFLYCLINF0001: Activating Infinispan subsystem.14:58:54,001 INFO  [org.jboss.as.naming] (ServerService Thread Pool -- 43) WFLYNAM0001: Activating Naming Subsystem14:58:54,006 INFO  [org.jboss.as.jsf] (ServerService Thread Pool -- 41) WFLYJSF0007: Activated the following JSF Implementations: [main]14:58:54,035 INFO  [org.wildfly.extension.io] (ServerService Thread Pool -- 34) WFLYIO001: Worker 'default' has auto-configured to 16 core threads with 128 task threads based on your 8 available processors14:58:54,056 INFO  [org.jboss.as.connector] (MSC service thread 1-9) WFLYJCA0009: Starting JCA Subsystem (IronJacamar 1.2.0.Beta3)14:58:54,071 INFO  [org.wildfly.extension.undertow] (MSC service thread 1-10) WFLYUT0003: Undertow 1.1.0.Beta6 starting14:58:54,071 INFO  [org.wildfly.extension.undertow] (ServerService Thread Pool -- 51) WFLYUT0003: Undertow 1.1.0.Beta6 starting14:58:54,090 INFO  [org.jboss.as.connector.subsystems.datasources] (ServerService Thread Pool -- 30) WFLYJCA0004: Deploying JDBC-compliant driver class org.h2.Driver (version 1.3)14:58:54,100 INFO  [org.jboss.as.connector.deployers.jdbc] (MSC service thread 1-7) WFLYJCA0018: Started Driver service with driver-name = h214:58:54,150 INFO  [org.jboss.as.naming] (MSC service thread 1-12) WFLYNAM0003: Starting Naming Service14:58:54,150 INFO  [org.jboss.as.mail.extension] (MSC service thread 1-7) WFLYMAIL0001: Bound mail session [java:jboss/mail/Default]14:58:54,155 INFO  [org.jboss.remoting] (MSC service thread 1-11) JBoss Remoting version 4.0.3.Final14:58:54,310 INFO  [org.wildfly.extension.undertow] (ServerService Thread Pool -- 51) WFLYUT0014: Creating file handler for path /Users/arungupta/tools/wildfly-9.0.0.Alpha1-SNAPSHOT/welcome-content14:58:54,349 INFO  [org.wildfly.extension.undertow] (MSC service thread 1-8) WFLYUT0012: Started server default-server.14:58:54,372 INFO  [org.wildfly.extension.undertow] (MSC service thread 1-5) WFLYUT0018: Host default-host starting14:58:54,449 INFO  [org.wildfly.extension.undertow] (MSC service thread 1-3) WFLYUT0006: Undertow HTTP listener default listening on /127.0.0.1:808014:58:54,701 INFO  [org.jboss.as.server.deployment.scanner] (MSC service thread 1-14) WFLYDS0013: Started FileSystemDeploymentService for directory /Users/arungupta/tools/wildfly-9.0.0.Alpha1-SNAPSHOT/standalone/deployments14:58:54,732 INFO  [org.jboss.as.connector.subsystems.datasources] (MSC service thread 1-9) WFLYJCA0001: Bound data source [java:jboss/datasources/ExampleDS]14:58:54,848 INFO  [org.jboss.ws.common.management] (MSC service thread 1-3) JBWS022052: Starting JBoss Web Services - Stack CXF Server 4.3.0.Final14:58:54,886 INFO  [org.jboss.as] (Controller Boot Thread) WFLYSRV0060: Http management interface listening on http://127.0.0.1:9990/management14:58:54,887 INFO  [org.jboss.as] (Controller Boot Thread) WFLYSRV0051: Admin console listening on http://127.0.0.1:999014:58:54,887 INFO  [org.jboss.as] (Controller Boot Thread) WFLYSRV0025: WildFly 1.0.0.Alpha5 "Kenny" started in 2667ms - Started 193 of 295 services (135 services are lazy, passive or on-demand) Note that is still very early in the development stages and workspace is constantly evolving. So things may be broken but you know that Red Hat is working actively on your favorite application server :-) Some useful references ... Feel free to subscribe to wildfly-dev alias and participate in the discussion Ask your questions on WildFly forum WildFly 9 docs (very early, mostly placeholder) Follow us at @WildFlyAS

Posted by on 29 August 2014 | 11:23 am

Ceylon JUG Tour - US 2014

Ceylon is a statically and strong-typed programming language, created by Red Hat. Version 1.0.0 was released late last year and 1.1 is coming soon. Gavin King (creator of Hibernate and CDI) and Stéphane Épardaud will be touring the USA East coast JUGs in October. At each venue, they will explain what Ceylon is, and why you will want to use it for your next production applications. The talks will be aimed at people who have never heard of Ceylon, or who have heard about it but want to know more. At the end of the evening you will be up to date with all that Ceylon is and has to offer. Their complete itinerary is explained at https://community.jboss.org/docs/DOC-52715. Don’t miss this opportunity. Make sure to show up at JUGs in your neighborhood and ask all your questions to the language creators!

Posted by on 29 August 2014 | 11:22 am

WildFly Administration Course by Alexis Hassler

Alexis Hassler (@alexishassler) is a software developer, specialized in Java and Java EE. He is using JBoss since version 2.0, more than twelve years ago. His business is to code for other companies or help them to improve the way they develop and deploy Java applications. He is co-leader of LyonJUG and helps to organize Mix-IT, an annual conference in Lyon. He recently concluded a WildFly administration course. Here is a brief Q&A with him: Q. You recently concluded a 4-day WildFly administration course. Tell us more about that. A. This course will help you understand the operation, configuration principles of WildFly. The core of the course is 3 days long. It deals with installation, deployment, administration tools, security and tuning. The forth day is on clustering and is optional. The recently concluded session was the first one and was conducted on-site in Brussels. Q. Who is this course targeted for ? A.  The course is designed for application server administrators. But it is useful for developers and software architects too. In fact, it is useful for anybody who have to work with WildFly. Q. Where can users register for this course ? A. The schedule of the course is on my company web site : http://www.sewatech.fr/formation-wildfly.html. Registration can be done by e-mail : formation -at- sewatech.fr. Q. How much of this course would be relevant for JBoss EAP users/customers ? A. JBoss EAP 6 is based on JBoss AS 7, but a lot of administration features of the latest EAP has been added in WildFly 8. So if you have EAP 6.2 or 6.3, this course will match ~ 80%. If you have an older EAP, a JBoss AS 7 course would be better (http://www.sewatech.fr/formation-jboss-7.html). JBoss EAP users is not the main target of this course.  RedHat has some great courses on JBoss Middleware Development and JBoss Middleware Administration. Q. How is your experience with JBoss / WildFly management tools ? A. Comparing with older versions of JBoss (I mean before JBoss AS 6), WildFly management tools are a huge step ahead. You can choose your tool: Web console Command line JMX HTTP API Java API Jboss-cli is the most useful one. It allow an admin to automate the whole setup his application server. The HTTP API is great too, as it allow to make custom tools in any language. For example, you can build your own simplified admin console in pure JavaScript. I don’t really like the Java API because, it’s a detyped API and it doesn’t fit with a compiled-time typed language. Maybe a Groovy guy could make a nice DSL on top of it. All in one, the greatest thing is that the different tools are really consistent : same data and same logic to manipulate these data. If you learn jboss-cli, it’s really easy to understand the HTTP API. Q. What tips would you give for users coming new to WildFly ? A. If you know JBoss AS 7, it will be easy. WildFly 8 is just the next version. Read the changelog and everything will be fne. If you know older versions of JBoss AS, forget everything you know, and start from the beginning with a good book. If you know Tomcat, be prepared to discover the power to "fly". And for everybody, learn the CLI tool. Q. Which application servers developers should choose, for both development and deployment ? A. It mainly depends on what you want to do. Tomcat can be great too, because it's really simple. When it comes with Java EE, TomEE is a very nice application server but lacks of administration tools. For Glassfish, we will see with the next versions if the current quality is maintained or if it comes back to a simple RI software. So, OK, WildFly is my favorite choice : great module system, great admin tools and great community. Q. What resources do you generally refer to when looking for help on WildFly ? A. For me, the main resource are the official documentation (https://docs.jboss.org/author/display/WFLY8/) and Francesco Marchioni’s blog (http://www.mastertheboss.com/). For a beginner, Francesco’s book WildFly 8, administration guide would be easier. The last resource I would recommend is the WildFly section on my wiki (http://jtips.info/index.php?title=Cat%C3%A9gorie:WildFly), but it’s in French.  

Posted by on 29 August 2014 | 11:21 am