Featured FREE Whitepapers

What's New Here?

apache-camel-logo

IDC Report on Business Value of using JBoss Fuse (with Apache Camel)

This is just a blog post that has more commercial nature, but you can’t have one without the other. In fact this is what keeps Apache Camel alive and doing so well, due also to its commercial success. This report may be of interest to people who are looking for hard evidence of the value add of using Apache Camel commercially, from products such as JBoss Fuse.         IDC interviewed 6 organizations that report achieving significant business value by using Red Hat® JBoss® Fuse, in particular, and making their application integration and development efforts more efficient and productive. These 6 organizations are achieving a 3 year average return on investment (ROI) of 488% and earning back their investments in JBoss Fuse in 8.2 months. The report is downloadable as-is (no registration) from Red Hat website at: http://www.redhat.com/en/resources/value-red-hat-integration-products Some of the highlights I see in relationship to Apache Camel are:JBoss Fuse allows developers to program in Java, which becomes more of an extension to the application rather than a separate development experience. This resulted in making JBoss Fuse easier to adopt. As one customer explained, “One of the biggest advantages that we see with this product is that the integration tool is provided as a domain language. So it’s like a natural extension of the Java language. You write integrations as if you’re writing Java code. That means that all of the skills you need to debug in Java are the same skills required when you write integrations in this language. You don’t have to go to another IDE or another toolset to understand how to write it. It’s just Java code.” Another customer cited the team’s desire to actually know and understand what the code is as a reason for adoption: “Before, we had a problem with the software, and actually being able to prove to the vendor that there was a problem before they would get around to fixing it is a lot harder if you can’t actually see any of the code. And this is not a small issue … In order to lodge a request, we would often have to prove to them by writing a sample program and prove that they are the cause of the issue — in a way that it’s reproducible in their environment.” A shipment and logistics company’s application integration and development efforts benefit from the flexibility of JBoss Fuse’s use of Apache Camel: “JBoss gives us the opportunity to help the developers in ways that wouldn’t necessarily be possible with a graphical user interface tool.” Customers also said that they benefit from Red Hat’s support and the ability to have access to and understand the code used for their applications. One customer praised Red Hat’s support: “The customer service support from Red Hat has been exceptional. They gave us access directly to the developers who are writing the code, whereas it can be hard to actually get access to developers with other solutions.”Just a note to the last bullet. Our support program allowed the customer direct access to myself and other Camel core committers, so we were able to help them quickly, and also fix and improve Apache Camel based on their issues and findings. The report has more details, and hard numbers stating the “before” vs “after” and their gains (development time, performance, and many others) and cost benefits, such as pretty graphs as shown below:Reference: IDC Report on Business Value of using JBoss Fuse (with Apache Camel) from our JCG partner Claus Ibsen at the Claus Ibsen riding the Apache Camel blog....
java-interview-questions-answers

EE Servlet 3: Simple Form Processing

Form handling in web application is like bread and butter for most Web developers. It will not be much use if we can not capture users input and process it. So I have included a simple FormServlet in my servlet3-example  that demonstrated few frequently used form inputs you might encounter. Here is how it looks like:               package zemian.servlet3example.web;import java.io.IOException; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import javax.servlet.ServletException; import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import zemian.service.logging.Logger;@WebServlet("/form") public class FormServlet extends HtmlWriterServlet { private static final Logger LOGGER = new Logger(FormServlet.class); @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { HtmlWriter html = createHtmlWriter(req, resp); String message = getMessage(req); html.header() .h(1, "User Data Form") .p(message) .println("<form method='post' action='form'>") .println("<p/>Username: <input type='text' name='username'/>") .println("<p/>Password: <input type='password' name='password'/>") .println("<p/>Choose a country: <select name='country' size='1'>") .println("<option default='true'>US</option>") .println("<option>China</option>") .println("<option>Korea</option>") .println("</select>") .println("<p/>Skills set: <input type='checkbox' name='skills' value='Java'/> Java") .println("<input type='checkbox' name='skills' value='Java EE'/>Java EE") .println("<input type='checkbox' name='skills' value='MySQL Database'/> MySQL Database") .println("<p/>Notes: <textarea name='notes' cols='50' rows='3'></textarea>") .println("<p/><input type='submit' value='Submit'/>") .println("</form>") .println(html.link("Back to Home", "/index")) .footer(); }@Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { LOGGER.info("Processing form."); Form form = new Form(); form.setUsername(req.getParameter("username")); form.setPassword(req.getParameter("password")); form.setNotes(req.getParameter("notes")); form.setCountry(req.getParameter("country")); String[] skills = req.getParameterValues("skills"); skills = (skills == null) ? new String[0] : skills; form.setSkills(Arrays.asList(skills)); req.setAttribute("message", "Processed: " + form); doGet(req, resp); } private String getMessage(HttpServletRequest req) { String message = (String)req.getAttribute("message"); if (message == null) { message = ""; } return message; } } As usual, most forms are display with a http GET request and then process it with a POST action. Take a closer look, and pay close attention to how Servlet handle single vs multi values inputs. These exist because HTML form might allow users to choose multiple values from a single input tag/widget. One common pattern developers do in form handling is to capture the input data into a “command object”, “transfer object”, or (in my example) “form” object; so that data can be pass into another layer of your application for further processing. This is a good design becuase it decouples the Web layer dependencies from your backend tier service layers. Another frequent dealt with area in form processing is data validation. If you capture your data as form object, then you will likely have two layers of validations. One layer is when you extract it right off the http request (usually from a String input), then you would validate such as is it a required field or optional, is the String value convertable to the expected and desiable type (integer or date etc). Second layer of validation might be further down in your service layer where you already have the form object constructed with correct types, but their values might not be valid per your application requirement. Most common invalid data is due to not conforming to the database constraints and thus not able to persist it. I didn’t provide example above on validation, but you can eaisly improve the Servlet and further explore this on your own. I like to mention one more note. There are many Java web frameworks out there that focus a LOT of attention on form handling, and they ought to help you develop application easier with less duplicated code. It is done usually with a very concrete programming model and style that, in many cases, shield you away from seing the HttpServletRequest object completly. All these are good (assuming the framework is a good quality one), but keep in mind that majority of cases when there is a problem occur, it’s mostly at the framework specific layer, or even more likely your own code that use the framwork. And then you will be spending most of your debugging time learning the framework specific domain, rather than the Servlet spec layer. For my example purpose I am trying to focus on EE API alone, so I will stay away from any extra frameworks other than the standard API. If you are a beginner, I strongly encourage you to study the Servlet API and see how form is handled, this gives you a more solid understanding of how the data come about in a web application. If you look further into the Java EE stack, it actually already has a framework that’s called JSF as part of EE 6 standards. It’s design is to help construct web pages as components model; and it lets you capture form data and automatically bind to a bean object in a much more smoother and integrated fashion. JSF is worthy of its own topic for future posts.Reference: EE Servlet 3: Simple Form Processing from our JCG partner Zemian Deng at the A Programmer’s Journal blog....
java-logo

Thread Magic Tricks: 5 Things You Never Knew You Can Do with Java Threads

What are some of the least known facts and use cases for Java threads? Some people like mountain climbing, others do sky diving. Me, I like Java. One of the things I love about it is that you never stop learning. The tools you use on a daily basis can often reveal a whole new side to them, with methods and interesting use cases you haven’t had a chance to see yet. Like threads for example. Actual threads. Or better put, the Thread class itself. Concurrent programming never stops posing challenges when we’re dealing with high scalability systems, but now we’ll talk about something a bit different. In this post you’ll see some of the lesser known yet useful techniques and methods that threads support. Whether you’re a beginner, advanced user or an expert Java developer, try to see which of these you already know and what comes off as new to you. Is there something else about threads you feel worth mentioning? I’d love to hear about it in the comments below. Let’s get started. Beginner 1. Thread names Each thread in your app has a name, a simple Java String that’s generated for it when the thread is constructed. The default name values go from “Thread-0″ to “Thread-1″, “Thread-2″ and so on. Now comes the more interesting part – Threads expose 2 ways you can use to set their names: 1. The thread constructors, here’s the simplest one: class SuchThread extends Thread {Public void run() { System.out.println ("Hi Mom! " + getName()); }}SuchThread wow = new SuchThread("much-name"); 2. The thread name setter: wow.setName(“Just another thread name”); Right, thread names are mutable. So other than setting a custom name when we’re instantiating them, we can change it during runtime. The name field itself is set as a simple String object. This means it can go up to 2³¹-1 characters long (Integer.MAX_VALUE). More than enough I’d say. Please note that this name doesn’t act like a unique ID, so threads can share the same name. Also, don’t try passing null as a name unless you want an exception to be thrown (“null” is ok though, I’m not judging!). Using thread names for debugging So now that you have access to thread names, following some naming conventions of your own could make your life much much easier when something bad happens. “Thread-6″ sounds a bit heartless, I’m sure you can think of a better name. Couple this with a self assigned transaction ID when handling user requests, append it to the thread’s name and you’ve considerably cut down your error solving time. A good practice to keep here is making sure you generate a UUID at every thread’s entry point to your app, and keep it consistent as the request travels between your nodes, processes and threads. Let’s take a look at this example, one of the worker threads in a certain thread pool hangs for too long. You run jstack to take a closer look and then you see this: “pool-1-thread-1″ #17 prio=5 os_prio=31 tid=0x00007f9d620c9800 nid=0x6d03 in Object.wait() [0x000000013ebcc000] Ok, “pool-1-thread-1″, why so serious? Let’s get to know you better and think of a more suitable name: Thread.currentThread().setName(Context + TID + Params + current Time, ...); Now when we run jstack again, things look much brighter: ”Queue Processing Thread, MessageID: AB5CAD, type: AnalyzeGraph, queue: ACTIVE_PROD, Transaction_ID: 5678956, Start Time: 30/12/2014 17:37″ #17 prio=5 os_prio=31 tid=0x00007f9d620c9800 nid=0x6d03 in Object.wait() [0x000000013ebcc000] We know what the thread is doing, when it got stuck, and we also have the transaction ID that started it all. You can retrace your steps, reproduce the error, isolate and solve it. To learn more about cool ways to use jstack you can check out this post right here. 2. Thread Priorities Another interesting field threads have is Priority. A thread’s Priority is a value between 1 (MIN_PRIORITY) to 10 (MAX_PRIORITY), and the default value for your main thread is 5 (NORM_PRIORITY). Each new thread gets the priority of its parent, so if you’re not playing with it manually, all your thread priorities are probably set to 5. This is also an often overlooked field of the Thread class, and we can access and manipulate it through the methods getPriority() and setPriority(). There’s no way to set this in the thread constructor. Who needs priorities anyhow? Of course not all threads are created equal, some require immediate attention from your CPU while others are just background tasks. Priorities are used to signal that to the OS thread scheduler. At Takipi, where we develop an error tracking and analysis tool, the thread that handles new exceptions for our users gets a MAX_PRIORITY, while threads that handle tasks like reporting new deployments are given a lower priority. One might expect that threads with a higher Priority get more time from the thread scheduler working with your JVM. Well, that’s not always the case. Each Java thread opens a new native thread on the OS level, and the Java priorities that you set are translated to native priorities in a different way for each platform. On Linux, you’ll also have to include the “-XX:+UseThreadPriorities” flag when running your app for them to be considered. With that said, thread priorities are still just recommendations that you provide. Compared to native Linux priorities, they don’t even cover the whole spectrum of values (1..99, and the effects of thread niceness that range between -20..20). The main takeaway is the importance of keeping your own logic that would ensure your priorities are reflected in the CPU time each thread gets, but it’s not recommended to rely solely on priorities.Advanced 3. Thread Local Storage This one is a bit different than the other creatures we talked about here. ThreadLocal is a concept that’s implemented off the Thread class (java.lang.ThreadLocal), but stores unique data for each thread. As it says on the tin, it provides you with Thread Local Storage, meaning you can create variables that are unique to each thread instance. Similar to the way you would have a thread name or priority, you can create custom fields that act as if they’re members of the Thread class. Isn’t that cool? But let’s not get too excited, there are some caveats ahead. It’s recommended to create a ThreadLocal in one of two ways: Either as a static variable or part of singleton where it doesn’t have to be static. Note that it lives on the global scope, yet acts local to each thread that’s able to access it. Here’s an example of a ThreadLocal variable holding a data structure of our own for easy access: public static class CriticalData { public int transactionId; public int username; }public static final ThreadLocal<CriticalData> globalData = new ThreadLocal<CriticalData>(); Once we have a ThreadLocal in our hands, we can access it with globalData.set() and globalData.get(). Global? It must be evil Not necessarily. A ThreadLocal variable can keep a transaction ID. This can come in handy when you have an uncaught exception bubbling up your code. A good practice is to have an UncaughtExceptionHandler in place, which we also get with the Thread class but have to implement ourselves. Once we reach that stage, there aren’t many hints as to what actually got us there. We’re left with the Thread object and can’t access any of the variables that go us there as the stack frames shut down. In our UncaughtExceptionHandler, as the thread takes its last breaths, ThreadLocal is pretty much one of the only things we have left. We can do something in the spirit of: System.err.println("Transaction ID " + globalData.get().transactionId); And just like that we added some valuable context to the error. One of the more creative ways to use ThreadLocal is by allocating a designated chunk of memory to be used as a buffer over and over by a worker thread. This can become useful depending on which side you’re on in the memory vs. CPU overhead tradeoff of course. That said, the thing to look out for is abuse of our memory space. ThreadLocal exists for a specific thread as long as it’s alive and will not be garbage collected unless you free it or the thread dies. So you better be careful when you use it and keep it simple. 4. User Threads and Daemon Threads Back to our Thread class. Each thread in our app receives either a User or a Daemon status. In other words, a foreground or a background thread. By default, the main thread is a User thread and each new thread gets the status of the thread that created it. So if you set a thread as Daemon, all the threads it creates will be marked as daemon as well. When the only threads left running in your app are of Daemon status, the process closes. To play around, check and change a threads status we have the Boolean .setDaemon(true) and .isDaemon() methods. When would you set a Daemon thread? You should change a thread’s status to Daemon when it’s not critical for it to end so the process could close. It takes off the hassle of closing the thread properly, stopping everything at once and let’s it end quickly. On the other hand, when there’s a thread that runs an operation that must end properly or else bad things will happen, make sure it’s set as a User thread. A critical transaction could be, for example, a database entry or completing an update that can’t be interrupted. Expert 5. Java Processor Affinity This part takes us closer to the hardware, where the code meets the metal. Processor affinity allows you to bind threads or processes to specific CPU cores. This means that whenever that specific thread executes, it would run exclusively on one certain core. Normally what would happen is that the OS thread scheduler would take on this role according to its own logic, possibly taking the thread priorities we mentioned earlier into account. The bargaining chip here is the CPUs cache. If a thread would only run on one specific core, it’s more likely it will get to enjoy having all its data ready for it on the cache. When the data is already there, there’s no need to reload it. The micro-seconds you save can be put to better use and the code will actually run on that time, making better use of the allocated CPU time it got. While some optimizations do exist on the OS level, and the hardware architecture also has an important role of course, using affinity can eliminate the chance of a thread switching cores. Since many factors are in play here, the best way to determine how processor affinity would affect your throughput is to embrace the habit of testing. While it may not always be significantly better, one of the benefits you might experience is a steady throughput. Affinity strategies can go down to a surgical level, depending on what there is to gain. The high frequency trading industry would be one of the places where these kind of things matter most. Testing processor affinity Java doesn’t have native support for processor affinity but that’s not the end of the story of course. On Linux, we can set a process affinity using the taskset command. Say we have a Java process running and we want to pin it to a specific CPU: taskset -c 1 “java AboutToBePinned” Or if its already running: taskset -c 1 <PID> Now, to get down to the thread level we’ll need to insert some new code. Luckily, there’s an open-source library that would help us do just that: Java-Thread-Affinity. Written by Peter Lawrey at OpenHFT, this is probably the most straightforward way to do this. Let’s see a quick example of pinning a thread, more of this is available on the library’s GitHub repo: AffinityLock al = AffinityLock.acquireLock(); And that’s it. More advanced options for acquiring the lock – taking into account different strategies for choosing the specific core – are available on GitHub. Conclusion We’ve seen 5 ways to look at threads: Thread names, thread local storage, priorities, daemon threads and affinity. Hope this helped shed a new light on the things you deal with on a daily basis, and would be glad to hear your comments! What other thread handling methods could fit in?Reference: Thread Magic Tricks: 5 Things You Never Knew You Can Do with Java Threads from our JCG partner Alex Zhitnitsky at the Takipi blog....
Jersey-logo

Building a HATEOAS API with JAX-RS and Spring

In my previous blog post I showed how easy Jersey can be configured with Spring Boot. My exploration on Spring Boot and Jersey did not end and I investigated the possibility of using Spring HATEOAS along with Jersey in Spring Boot application. Spring HATEOS allows creating REST representations that follow the HATEOAS principle and (as of writing this article) has basic JAX-RS support for working with links. In this blog post I will share some examples of how I integrated Spring HATEOAS with Jersey in a Spring Boot application. Introduction As the foundation for this article I used the example I created previously: (https://github.com/kolorobot/spring-boot-jersey-demo). To get started with Spring HATEOAS I added the valid dependency to build.gradle: compile("org.springframework.hateoas:spring-hateoas:0.16.0.RELEASE") Quick approach with Resources helper The quickest approach for generating representation of entity object (Customer) is using Spring HATEOAS Resource and Resources helpers. The latter wrap a collection of entities returned by CustomerRepository. To generate a link I used JaxRsLinkBuilder which helps building resources links to JAX-RS resources by discovering the paths based on the @Path annotation. @Component @Path("/customer") @Produces(MediaType.APPLICATION_JSON) public class CustomerController {@Inject private CustomerRepository customerRepository;@GET public Response findAll() { Resources<Customer> resources = new Resources<>( customerRepository.findAll(), JaxRsLinkBuilder .linkTo(CustomerController.class) .withSelfRel() ); return Response.ok(resources).build(); } The result of calling the above method will be a collection resource with a self rel link: { "links": [ { "rel": "self", "href": "http://localhost:8080/customer" } ], "content": [ { "id": 1, "firstname": "Dave", "lastname": "Matthews", "emailAddress": { "value": "dave@dmband.com" } } ] } Building representations with ResourceAssemblerSupport class The Resource, Resources, PagedResources helpers are pretty handy, but there are situations where more control over created resources is needed. To create custom transfer object from an entity ResourceSupport base class can be used: public class CustomerResource extends ResourceSupport {private String fullName; private String email;} To assemble CustomerResource from an entity and automatically add self rel link to it ResourceAssemblerSupport class should be used. Basically this class is responsible for instantiating the resource and adding a link with rel self pointing to the resource: public class CustomerResourceAssembler extends ResourceAssemblerSupport<Customer, CustomerResource> {public CustomerResourceAssembler() { super(CustomerController.class, CustomerResource.class); }@Override public CustomerResource toResource(Customer entity) { CustomerResource resource = createResourceWithId( entity.getId(), entity );// initialize the resourcereturn resource; } } The problem I had with the above code is that ResourceAssemblerSupport class internally uses a link builder for building links to Spring MVC controllers (ControllerLinkBuilder). This causes that links are invalid. I did not find other way than creating a new support class that extends from ResourceAssemblerSupport and overrides the behavior of its parent: public abstract class JaxRsResourceAssemblerSupport<T, D extends ResourceSupport> extends ResourceAssemblerSupport<T, D> {private final Class<?> controllerClass;public JaxRsResourceAssemblerSupport( Class<?> controllerClass, Class<D> resourceType) {super(controllerClass, resourceType); this.controllerClass = controllerClass; }@Override protected D createResourceWithId(Object id, T entity, Object... parameters) { Assert.notNull(entity); Assert.notNull(id);D instance = instantiateResource(entity);instance.add( JaxRsLinkBuilder.linkTo(controllerClass, parameters) .slash(id) .withSelfRel()); return instance; } } I don’t really like the above solution as I needed to copy and paste some code, but I did not find a better way to achieve what I wanted. My assembler extends now from newly created JaxRsResourceAssemblerSupport: public class CustomerResourceAssembler extends JaxRsResourceAssemblerSupport<Customer, CustomerResource> {} Finally I could modify controller’s method to return resources assembled by my assembler. Please note the ResourceAssemblerSupport provides convenient method to converts all given entities into resources: @GET @Path("/resources") public Response findAll() { Iterable<Customer> customers = customerRepository.findAll();CustomerResourceAssembler assembler = new CustomerResourceAssembler(); List<CustomerResource> resources = assembler.toResources(customers);return Response.ok(wrapped).build(); } To add a link with self rel link to the collection resource, I needed to wrap it using previously mentioned Resources class: // wrap to add link Resources<CustomerResource> wrapped = new Resources<>(resources); wrapped.add( JaxRsLinkBuilder .linkTo(CustomerController.class) .withSelfRel() ); Now the returned representation looks more HATEOAS: { "links": [ { "rel": "self", "href": "http://localhost:8080/customer" } ], "content": [ { "fullName": "Matthews, Dave", "email": "dave@dmband.com", "links": [ { "rel": "self", "href": "http://localhost:8080/customer/1" } ] } ] } Using LinksBuilder The EntityLinks interface provide API to create links based on entity type and are available for dependency injection when @EnableEntityLinks or @EnableHypermadiaSupport are used with @ExposesResourceFor. @ExposesResourceForexposes which entity type the Spring MVC controller or JAX-RS resource manages. In configuration class we need to activate entity links: @SpringBootApplication @EnableEntityLinks public class Application {} Note: Please note that when using entity links and @EnableEntityLinks the following dependency must be on the classpath: compile("org.springframework.plugin:spring-plugin-core:1.1.0.RELEASE") Any JAX-RS resource supporting an entity type must be marked with @ExposesResourceFor, so EntityLinks can be injected: @ExposesResourceFor(Customer.class) public class CustomerController { @Inject private EntityLinks entityLinks; } Basically, EntityLinks interface provides methods returning links to a collection resource or a single resource. Example: Link selfRel = entityLinks.linkToSingleResource( Customer.class, customer.getId() ).withSelfRel(); Summary Spring HATEOAS is not the only option to build HATEOAS API with JAX-RS and Jersey, but with the possibility of having Jersey in a Spring Boot application Spring HATEOAS may be a nice supplement, especially that it was designed with JAX-RS in mind. Note: This article is just a research I conducted regarding the topic described. I did not use the approach in any project yet. ResourcesProject source code: https://github.com/kolorobot/spring-boot-jersey-demo Spring HATEOAS project page: https://github.com/spring-projects/spring-hateoas and sample: https://github.com/olivergierke/spring-hateoas-sampleReference: Building a HATEOAS API with JAX-RS and Spring from our JCG partner Rafal Borowiec at the Codeleak.pl blog....
docker-logo

Docker orchestration using Fig

Tech Tip #65 showed how to run a Java EE 7 application using WildFly and MySQL in two separate containers. It required to explicitly start the two containers, and link them using --link. This defining and controlling a multi-container service is a common design pattern in order to get an application up and going. Meet Fig – Docker Orchestration Tool. Fig allows to:      Define multiple containers in a single configuration file Create dependencies between two containers by creating links between them Start containers in the right sequenceLet’s get started!Install Fig as: curl -L https://github.com/docker/fig/releases/download/1.0.1/fig-`uname-s`-`uname -m` > /usr/local/bin/fig; chmod +x /usr/local/bin/figEntry point to Fig is a configuration file that defines the containers and their dependencies. The equivalent configuration file from Tech Tip #65 is: mysqldb: image: mysql:latest environment: MYSQL_DATABASE: sample MYSQL_USER: mysql MYSQL_PASSWORD: mysql MYSQL_ROOT_PASSWORD: supersecret mywildfly: image: arungupta/wildfly-mysql-javaee7 links: - mysqldb:db ports: - 8080:8080 This YML-based configuration file has:Two containers defined by the name “mysqldb” and “mywildfly” Image names are defined using “image” Environment variables for the MySQL container are defined in “environment” MySQL container is linked with WildFly container using “links” Port forwarding is achieved using “ports”All the containers can be started, in detached mode, by giving the command: fig up -d The output is shown as: Creating wildflymysqljavaee7_mysqldb_1... Creating wildflymysqljavaee7_mywildfly_1... Fig commands allow to monitor and update the status of the containers:Logs can be seen as: fig logsContainer status can be seen by giving the command: fig ps to show the output as:Name Command State Ports ---------------------------------------------------------------------------------------------- wildflymysqljavaee7_mysqldb_1 /entrypoint.sh mysqld --da ... Up 3306/tcp wildflymysqljavaee7_mywildfly_1 /opt/jboss/wildfly/customi ... Up 0.0.0.0:8080->8080/tcp, 9990/tcpContainers can be stopped as: fig stopAlternatively, containers can be started in foreground by giving the command: fig up and the output is seen as: wildfly-mysql-javaee7> fig up Creating wildflymysqljavaee7_mysqldb_1... Creating wildflymysqljavaee7_mywildfly_1... Attaching to wildflymysqljavaee7_mysqldb_1, wildflymysqljavaee7_mywildfly_1 mywildfly_1 | => Starting WildFly server mywildfly_1 | => Waiting for the server to boot mysqldb_1 | 2014-12-23 18:28:10 0 [Warning] TIMESTAMP with implicit DEFAULT value is deprecated. Please use --explicit_defaults_for_timestamp server option (see documentation for more details). mysqldb_1 | 2014-12-23 18:28:10 12 [Note] InnoDB: Using atomics to ref count buffer pool pages mysqldb_1 | 2014-12-23 18:28:10 12 [Note] InnoDB: The InnoDB memory heap is disabled mysqldb_1 | 2014-12-23 18:28:10 12 [Note] InnoDB: Mutexes and rw_locks use GCC atomic builtins mysqldb_1 | 2014-12-23 18:28:10 12 [Note] InnoDB: Memory barrier is not used mysqldb_1 | 2014-12-23 18:28:10 12 [Note] InnoDB: Compressed tables use zlib 1.2.3 mysqldb_1 | 2014-12-23 18:28:10 12 [Note] InnoDB: Using Linux native AIO mysqldb_1 | 2014-12-23 18:28:10 12 [Note] InnoDB: Not using CPU crc32 instructions mysqldb_1 | 2014-12-23 18:28:10 12 [Note] InnoDB: Initializing buffer pool, size = 128.0M mysqldb_1 | 2014-12-23 18:28:10 12 [Note] InnoDB: Completed initialization of buffer pool mysqldb_1 | 2014-12-23 18:28:10 12 [Note] InnoDB: The first specified data file ./ibdata1 did not exist: a new database to be created! mysqldb_1 | 2014-12-23 18:28:10 12 [Note] InnoDB: Setting file ./ibdata1 size to 12 MB mysqldb_1 | 2014-12-23 18:28:10 12 [Note] InnoDB: Database physically writes the file full: wait... mysqldb_1 | 2014-12-23 18:28:10 12 [Note] InnoDB: Setting log file ./ib_logfile101 size to 48 MB mysqldb_1 | 2014-12-23 18:28:10 12 [Note] InnoDB: Setting log file ./ib_logfile1 size to 48 MB mysqldb_1 | 2014-12-23 18:28:10 12 [Note] InnoDB: Renaming log file ./ib_logfile101 to ./ib_logfile0 mysqldb_1 | 2014-12-23 18:28:10 12 [Warning] InnoDB: New log files created, LSN=45781 mysqldb_1 | 2014-12-23 18:28:10 12 [Note] InnoDB: Doublewrite buffer not found: creating new mysqldb_1 | 2014-12-23 18:28:10 12 [Note] InnoDB: Doublewrite buffer created mysqldb_1 | 2014-12-23 18:28:10 12 [Note] InnoDB: 128 rollback segment(s) are active. mysqldb_1 | 2014-12-23 18:28:10 12 [Warning] InnoDB: Creating foreign key constraint system tables. mysqldb_1 | 2014-12-23 18:28:10 12 [Note] InnoDB: Foreign key constraint system tables created mysqldb_1 | 2014-12-23 18:28:10 12 [Note] InnoDB: Creating tablespace and datafile system tables. mysqldb_1 | 2014-12-23 18:28:10 12 [Note] InnoDB: Tablespace and datafile system tables created. mysqldb_1 | 2014-12-23 18:28:10 12 [Note] InnoDB: Waiting for purge to start mysqldb_1 | 2014-12-23 18:28:10 12 [Note] InnoDB: 5.6.22 started; log sequence number 0 mywildfly_1 | ========================================================================= mywildfly_1 | mywildfly_1 | JBoss Bootstrap Environment mywildfly_1 | mywildfly_1 | JBOSS_HOME: /opt/jboss/wildfly mywildfly_1 | mywildfly_1 | JAVA: /usr/lib/jvm/java/bin/java mywildfly_1 | mywildfly_1 | JAVA_OPTS: -server -Xms64m -Xmx512m -XX:MaxPermSize=256m -Djava.net.preferIPv4Stack=true -Djboss.modules.system.pkgs=org.jboss.byteman -Djava.awt.headless=true mywildfly_1 | mywildfly_1 | ========================================================================= mywildfly_1 | mysqldb_1 | 2014-12-23 18:28:10 12 [Note] Binlog end mysqldb_1 | 2014-12-23 18:28:10 12 [Note] InnoDB: FTS optimize thread exiting. mysqldb_1 | 2014-12-23 18:28:10 12 [Note] InnoDB: Starting shutdown... mywildfly_1 | 18:28:11,257 INFO [org.jboss.modules] (main) JBoss Modules version 1.3.3.Final mywildfly_1 | 18:28:11,543 INFO [org.jboss.msc] (main) JBoss MSC version 1.2.2.Final mywildfly_1 | 18:28:11,631 INFO [org.jboss.as] (MSC service thread 1-6) JBAS015899: WildFly 8.2.0.Final "Tweek" starting mysqldb_1 | 2014-12-23 18:28:12 12 [Note] InnoDB: Shutdown completed; log sequence number 1625977 mywildfly_1 | 18:28:12,621 INFO [org.jboss.as.server] (Controller Boot Thread) JBAS015888: Creating http management service using socket-binding (management-http) mywildfly_1 | 18:28:12,642 INFO [org.xnio] (MSC service thread 1-10) XNIO version 3.3.0.Final mywildfly_1 | 18:28:12,652 INFO [org.xnio.nio] (MSC service thread 1-10) XNIO NIO Implementation Version 3.3.0.Final mywildfly_1 | 18:28:12,697 INFO [org.jboss.as.clustering.infinispan] (ServerService Thread Pool -- 32) JBAS010280: Activating Infinispan subsystem. mywildfly_1 | 18:28:12,698 INFO [org.wildfly.extension.io] (ServerService Thread Pool -- 31) WFLYIO001: Worker 'default' has auto-configured to 16 core threads with 128 task threads based on your 8 available processors mywildfly_1 | 18:28:12,880 INFO [org.jboss.as.connector.subsystems.datasources] (ServerService Thread Pool -- 27) JBAS010403: Deploying JDBC-compliant driver class org.h2.Driver (version 1.3) mywildfly_1 | 18:28:12,917 INFO [org.jboss.as.naming] (ServerService Thread Pool -- 40) JBAS011800: Activating Naming Subsystem mywildfly_1 | 18:28:12,987 WARN [org.jboss.as.txn] (ServerService Thread Pool -- 46) JBAS010153: Node identifier property is set to the default value. Please make sure it is unique. mywildfly_1 | 18:28:13,002 INFO [org.jboss.as.security] (ServerService Thread Pool -- 45) JBAS013171: Activating Security Subsystem mywildfly_1 | 18:28:13,082 INFO [org.jboss.as.connector.logging] (MSC service thread 1-7) JBAS010408: Starting JCA Subsystem (IronJacamar 1.1.9.Final) mywildfly_1 | 18:28:13,084 INFO [org.jboss.as.jsf] (ServerService Thread Pool -- 38) JBAS012615: Activated the following JSF Implementations: [main] mywildfly_1 | 18:28:13,088 INFO [org.jboss.as.security] (MSC service thread 1-15) JBAS013170: Current PicketBox version=4.0.21.Final mywildfly_1 | 18:28:13,097 INFO [org.wildfly.extension.undertow] (ServerService Thread Pool -- 47) JBAS017502: Undertow 1.1.0.Final starting mywildfly_1 | 18:28:13,098 INFO [org.wildfly.extension.undertow] (MSC service thread 1-8) JBAS017502: Undertow 1.1.0.Final starting mywildfly_1 | 18:28:13,109 INFO [org.jboss.as.connector.deployers.jdbc] (MSC service thread 1-6) JBAS010417: Started Driver service with driver-name = h2 mywildfly_1 | 18:28:13,132 INFO [org.jboss.as.webservices] (ServerService Thread Pool -- 48) JBAS015537: Activating WebServices Extension mywildfly_1 | 18:28:13,355 INFO [org.jboss.remoting] (MSC service thread 1-10) JBoss Remoting version 4.0.6.Final mywildfly_1 | 18:28:13,502 INFO [org.jboss.as.naming] (MSC service thread 1-13) JBAS011802: Starting Naming Service mywildfly_1 | 18:28:13,503 INFO [org.jboss.as.mail.extension] (MSC service thread 1-4) JBAS015400: Bound mail session mysqldb_1 | OK mysqldb_1 | mywildfly_1 | 18:28:14,161 INFO [org.wildfly.extension.undertow] (ServerService Thread Pool -- 47) JBAS017527: Creating file handler for path /opt/jboss/wildfly/welcome-content mysqldb_1 | Filling help tables...2014-12-23 18:28:14 0 [Warning] TIMESTAMP with implicit DEFAULT value is deprecated. Please use --explicit_defaults_for_timestamp server option (see documentation for more details). mysqldb_1 | 2014-12-23 18:28:14 35 [Note] InnoDB: Using atomics to ref count buffer pool pages mysqldb_1 | 2014-12-23 18:28:14 35 [Note] InnoDB: The InnoDB memory heap is disabled mysqldb_1 | 2014-12-23 18:28:14 35 [Note] InnoDB: Mutexes and rw_locks use GCC atomic builtins mysqldb_1 | 2014-12-23 18:28:14 35 [Note] InnoDB: Memory barrier is not used mysqldb_1 | 2014-12-23 18:28:14 35 [Note] InnoDB: Compressed tables use zlib 1.2.3 mysqldb_1 | 2014-12-23 18:28:14 35 [Note] InnoDB: Using Linux native AIO mysqldb_1 | 2014-12-23 18:28:14 35 [Note] InnoDB: Not using CPU crc32 instructions mysqldb_1 | 2014-12-23 18:28:14 35 [Note] InnoDB: Initializing buffer pool, size = 128.0M mywildfly_1 | 18:28:14,190 INFO [org.wildfly.extension.undertow] (MSC service thread 1-9) JBAS017525: Started server default-server. mysqldb_1 | 2014-12-23 18:28:14 35 [Note] InnoDB: Completed initialization of buffer pool mysqldb_1 | 2014-12-23 18:28:14 35 [Note] InnoDB: Highest supported file format is Barracuda. mysqldb_1 | 2014-12-23 18:28:14 35 [Note] InnoDB: 128 rollback segment(s) are active. mysqldb_1 | 2014-12-23 18:28:14 35 [Note] InnoDB: Waiting for purge to start mywildfly_1 | 18:28:14,271 INFO [org.wildfly.extension.undertow] (MSC service thread 1-16) JBAS017531: Host default-host starting mysqldb_1 | 2014-12-23 18:28:14 35 [Note] InnoDB: 5.6.22 started; log sequence number 1625977 mywildfly_1 | 18:28:14,366 INFO [org.wildfly.extension.undertow] (MSC service thread 1-9) JBAS017519: Undertow HTTP listener default listening on /0.0.0.0:8080 mysqldb_1 | 2014-12-23 18:28:14 35 [Note] Binlog end mysqldb_1 | 2014-12-23 18:28:14 35 [Note] InnoDB: FTS optimize thread exiting. mysqldb_1 | 2014-12-23 18:28:14 35 [Note] InnoDB: Starting shutdown... mywildfly_1 | 18:28:14,548 INFO [org.jboss.as.server.deployment.scanner] (MSC service thread 1-7) JBAS015012: Started FileSystemDeploymentService for directory /opt/jboss/wildfly/standalone/deployments mywildfly_1 | 18:28:14,584 INFO [org.jboss.as.connector.subsystems.datasources] (MSC service thread 1-14) JBAS010400: Bound data source mywildfly_1 | 18:28:14,697 INFO [org.jboss.ws.common.management] (MSC service thread 1-15) JBWS022052: Starting JBoss Web Services - Stack CXF Server 4.3.2.Final mywildfly_1 | 18:28:14,766 INFO [org.jboss.as] (Controller Boot Thread) JBAS015961: Http management interface listening on http://127.0.0.1:9990/management mywildfly_1 | 18:28:14,766 INFO [org.jboss.as] (Controller Boot Thread) JBAS015951: Admin console listening on http://127.0.0.1:9990 mywildfly_1 | 18:28:14,768 INFO [org.jboss.as] (Controller Boot Thread) JBAS015874: WildFly 8.2.0.Final "Tweek" started in 3852ms - Started 184 of 234 services (82 services are lazy, passive or on-demand) mywildfly_1 | => Executing the commands mywildfly_1 | => MYSQL_HOST: mywildfly_1 | => MYSQL_PORT: mywildfly_1 | => MYSQL (host): 172.17.0.4 mywildfly_1 | => MYSQL (port): 3306 mysqldb_1 | 2014-12-23 18:28:16 35 [Note] InnoDB: Shutdown completed; log sequence number 1625987 mywildfly_1 | [standalone@localhost:9990 /] batch mywildfly_1 | [standalone@localhost:9990 / #] mywildfly_1 | [standalone@localhost:9990 / #] # Add MySQL module mywildfly_1 | [standalone@localhost:9990 / #] module add --name=com.mysql --resources=/opt/jboss/wildfly/customization/mysql-connector-java-5.1.31-bin.jar --dependencies=javax.api,javax.transaction.api mywildfly_1 | [standalone@localhost:9990 / #] mywildfly_1 | [standalone@localhost:9990 / #] # Add MySQL driver mywildfly_1 | [standalone@localhost:9990 / #] /subsystem=datasources/jdbc-driver=mysql:add(driver-name=mysql,driver-module-name=com.mysql,driver-xa-datasource-class-name=com.mysql.jdbc.jdbc2.optional.MysqlXADataSource) mywildfly_1 | [standalone@localhost:9990 / #] mywildfly_1 | [standalone@localhost:9990 / #] # Add the datasource mywildfly_1 | [standalone@localhost:9990 / #] #data-source add --name=mysqlDS --driver-name=mysql --jndi-name=java:jboss/datasources/ExampleMySQLDS --connection-url=jdbc:mysql://:/sample?useUnicode=true&characterEncoding=UTF-8 --user-name=mysql --password=mysql --use-ccm=false --max-pool-size=25 --blocking-timeout-wait-millis=5000 --enabled=true mywildfly_1 | [standalone@localhost:9990 / #] mywildfly_1 | [standalone@localhost:9990 / #] data-source add --name=mysqlDS --driver-name=mysql --jndi-name=java:jboss/datasources/ExampleMySQLDS --connection-url=jdbc:mysql://172.17.0.4:3306/sample?useUnicode=true&characterEncoding=UTF-8 --user-name=mysql --password=mysql --use-ccm=false --max-pool-size=25 --blocking-timeout-wait-millis=5000 --enabled=true mywildfly_1 | [standalone@localhost:9990 / #] mywildfly_1 | [standalone@localhost:9990 / #] # Execute the batch mywildfly_1 | [standalone@localhost:9990 / #] run-batch mywildfly_1 | 18:28:16,957 INFO [org.jboss.as.connector.subsystems.datasources] (management-handler-thread - 4) JBAS010404: Deploying non-JDBC-compliant driver class com.mysql.jdbc.Driver (version 5.1) mywildfly_1 | 18:28:16,963 INFO [org.jboss.as.connector.deployers.jdbc] (MSC service thread 1-11) JBAS010417: Started Driver service with driver-name = mysql mywildfly_1 | 18:28:16,976 INFO [org.jboss.as.connector.subsystems.datasources] (MSC service thread 1-5) JBAS010400: Bound data source mywildfly_1 | The batch executed successfully mywildfly_1 | [standalone@localhost:9990 /] mywildfly_1 | => Shutting down WildFly mysqldb_1 | OK mysqldb_1 | mysqldb_1 | To start mysqld at boot time you have to copy mysqldb_1 | support-files/mysql.server to the right place for your system mysqldb_1 | mysqldb_1 | PLEASE REMEMBER TO SET A PASSWORD FOR THE MySQL root USER ! mysqldb_1 | To do so, start the server, then issue the following commands: mysqldb_1 | mysqldb_1 | ./bin/mysqladmin -u root password 'new-password' mysqldb_1 | ./bin/mysqladmin -u root -h 8aca3b20ca40 password 'new-password' mysqldb_1 | mysqldb_1 | Alternatively you can run: mysqldb_1 | mysqldb_1 | ./bin/mysql_secure_installation mysqldb_1 | mysqldb_1 | which will also give you the option of removing the test mysqldb_1 | databases and anonymous user created by default. This is mysqldb_1 | strongly recommended for production servers. mysqldb_1 | mysqldb_1 | See the manual for more instructions. mysqldb_1 | mysqldb_1 | You can start the MySQL daemon with: mysqldb_1 | mysqldb_1 | cd . ; ./bin/mysqld_safe & mysqldb_1 | mysqldb_1 | You can test the MySQL daemon with mysql-test-run.pl mysqldb_1 | mysqldb_1 | cd mysql-test ; perl mysql-test-run.pl mysqldb_1 | mysqldb_1 | Please report any problems at http://bugs.mysql.com/ mysqldb_1 | mysqldb_1 | The latest information about MySQL is available on the web at mysqldb_1 | mysqldb_1 | http://www.mysql.com mysqldb_1 | mysqldb_1 | Support MySQL by buying support/licenses at http://shop.mysql.com mysqldb_1 | mysqldb_1 | New default config file was created as ./my.cnf and mysqldb_1 | will be used by default by the server when you start it. mysqldb_1 | You may edit this file to change server settings mysqldb_1 | mysqldb_1 | 2014-12-23 18:28:17 0 [Warning] TIMESTAMP with implicit DEFAULT value is deprecated. Please use --explicit_defaults_for_timestamp server option (see documentation for more details). mysqldb_1 | 2014-12-23 18:28:17 1 [Note] Plugin 'FEDERATED' is disabled. mysqldb_1 | 2014-12-23 18:28:17 1 [Note] InnoDB: Using atomics to ref count buffer pool pages mysqldb_1 | 2014-12-23 18:28:17 1 [Note] InnoDB: The InnoDB memory heap is disabled mysqldb_1 | 2014-12-23 18:28:17 1 [Note] InnoDB: Mutexes and rw_locks use GCC atomic builtins mysqldb_1 | 2014-12-23 18:28:17 1 [Note] InnoDB: Memory barrier is not used mysqldb_1 | 2014-12-23 18:28:17 1 [Note] InnoDB: Compressed tables use zlib 1.2.3 mysqldb_1 | 2014-12-23 18:28:17 1 [Note] InnoDB: Using Linux native AIO mysqldb_1 | 2014-12-23 18:28:17 1 [Note] InnoDB: Not using CPU crc32 instructions mysqldb_1 | 2014-12-23 18:28:17 1 [Note] InnoDB: Initializing buffer pool, size = 128.0M mysqldb_1 | 2014-12-23 18:28:17 1 [Note] InnoDB: Completed initialization of buffer pool mysqldb_1 | 2014-12-23 18:28:17 1 [Note] InnoDB: Highest supported file format is Barracuda. mysqldb_1 | 2014-12-23 18:28:17 1 [Note] InnoDB: 128 rollback segment(s) are active. mysqldb_1 | 2014-12-23 18:28:17 1 [Note] InnoDB: Waiting for purge to start mysqldb_1 | 2014-12-23 18:28:17 1 [Note] InnoDB: 5.6.22 started; log sequence number 1625987 mysqldb_1 | 2014-12-23 18:28:17 1 [Warning] No existing UUID has been found, so we assume that this is the first time that this server has been started. Generating a new UUID: 76e25b07-8ad1-11e4-9167-0242ac110004. mysqldb_1 | 2014-12-23 18:28:17 1 [Note] Server hostname (bind-address): '*'; port: 3306 mysqldb_1 | 2014-12-23 18:28:17 1 [Note] IPv6 is available. mysqldb_1 | 2014-12-23 18:28:17 1 [Note] - '::' resolves to '::'; mysqldb_1 | 2014-12-23 18:28:17 1 [Note] Server socket created on IP: '::'. mysqldb_1 | 2014-12-23 18:28:17 1 [Note] Event Scheduler: Loaded 0 events mysqldb_1 | 2014-12-23 18:28:17 1 [Note] Execution of init_file '/tmp/mysql-first-time.sql' started. mysqldb_1 | 2014-12-23 18:28:17 1 [Note] Execution of init_file '/tmp/mysql-first-time.sql' ended. mysqldb_1 | 2014-12-23 18:28:17 1 [Note] mysqld: ready for connections. mysqldb_1 | Version: '5.6.22' socket: '/tmp/mysql.sock' port: 3306 MySQL Community Server (GPL) mywildfly_1 | {"outcome" => "success"} mywildfly_1 | => Restarting WildFly mywildfly_1 | 18:28:17,931 INFO [org.jboss.as.connector.subsystems.datasources] (MSC service thread 1-15) JBAS010409: Unbound data source mywildfly_1 | 18:28:17,931 INFO [org.jboss.as.connector.subsystems.datasources] (MSC service thread 1-11) JBAS010409: Unbound data source mywildfly_1 | 18:28:17,942 INFO [org.wildfly.extension.undertow] (MSC service thread 1-5) JBAS017532: Host default-host stopping mywildfly_1 | 18:28:17,946 INFO [org.jboss.as.connector.deployers.jdbc] (MSC service thread 1-11) JBAS010418: Stopped Driver service with driver-name = mysql mywildfly_1 | 18:28:17,956 INFO [org.jboss.as.connector.deployers.jdbc] (MSC service thread 1-8) JBAS010418: Stopped Driver service with driver-name = h2 mywildfly_1 | 18:28:17,981 INFO [org.wildfly.extension.undertow] (MSC service thread 1-8) JBAS017521: Undertow HTTP listener default suspending mywildfly_1 | 18:28:18,004 INFO [org.wildfly.extension.undertow] (MSC service thread 1-8) JBAS017520: Undertow HTTP listener default stopped, was bound to /0.0.0.0:8080 mywildfly_1 | 18:28:18,007 INFO [org.wildfly.extension.undertow] (MSC service thread 1-5) JBAS017506: Undertow 1.1.0.Final stopping mywildfly_1 | ========================================================================= mywildfly_1 | mywildfly_1 | JBoss Bootstrap Environment mywildfly_1 | mywildfly_1 | JBOSS_HOME: /opt/jboss/wildfly mywildfly_1 | mywildfly_1 | JAVA: /usr/lib/jvm/java/bin/java mywildfly_1 | mywildfly_1 | JAVA_OPTS: -server -Xms64m -Xmx512m -XX:MaxPermSize=256m -Djava.net.preferIPv4Stack=true -Djboss.modules.system.pkgs=org.jboss.byteman -Djava.awt.headless=true mywildfly_1 | mywildfly_1 | ========================================================================= mywildfly_1 | mywildfly_1 | 18:28:18,082 INFO [org.jboss.as] (MSC service thread 1-10) JBAS015950: WildFly 8.2.0.Final "Tweek" stopped in 148ms mywildfly_1 | 18:28:18,438 INFO [org.jboss.modules] (main) JBoss Modules version 1.3.3.Final mywildfly_1 | 18:28:18,691 INFO [org.jboss.msc] (main) JBoss MSC version 1.2.2.Final mywildfly_1 | 18:28:18,769 INFO [org.jboss.as] (MSC service thread 1-7) JBAS015899: WildFly 8.2.0.Final "Tweek" starting mywildfly_1 | 18:28:19,737 INFO [org.jboss.as.server] (Controller Boot Thread) JBAS015888: Creating http management service using socket-binding (management-http) mywildfly_1 | 18:28:19,756 INFO [org.xnio] (MSC service thread 1-12) XNIO version 3.3.0.Final mywildfly_1 | 18:28:19,765 INFO [org.xnio.nio] (MSC service thread 1-12) XNIO NIO Implementation Version 3.3.0.Final mywildfly_1 | 18:28:19,798 INFO [org.jboss.as.clustering.infinispan] (ServerService Thread Pool -- 32) JBAS010280: Activating Infinispan subsystem. mywildfly_1 | 18:28:19,802 INFO [org.wildfly.extension.io] (ServerService Thread Pool -- 31) WFLYIO001: Worker 'default' has auto-configured to 16 core threads with 128 task threads based on your 8 available processors mywildfly_1 | 18:28:19,834 INFO [org.jboss.as.naming] (ServerService Thread Pool -- 40) JBAS011800: Activating Naming Subsystem mywildfly_1 | 18:28:19,837 INFO [org.jboss.as.security] (ServerService Thread Pool -- 45) JBAS013171: Activating Security Subsystem mywildfly_1 | 18:28:19,843 WARN [org.jboss.as.txn] (ServerService Thread Pool -- 46) JBAS010153: Node identifier property is set to the default value. Please make sure it is unique. mywildfly_1 | 18:28:19,846 INFO [org.jboss.as.security] (MSC service thread 1-9) JBAS013170: Current PicketBox version=4.0.21.Final mywildfly_1 | 18:28:19,868 INFO [org.jboss.as.jsf] (ServerService Thread Pool -- 38) JBAS012615: Activated the following JSF Implementations: [main] mywildfly_1 | 18:28:19,892 INFO [org.jboss.as.connector.logging] (MSC service thread 1-10) JBAS010408: Starting JCA Subsystem (IronJacamar 1.1.9.Final) mywildfly_1 | 18:28:19,902 INFO [org.jboss.as.webservices] (ServerService Thread Pool -- 48) JBAS015537: Activating WebServices Extension mywildfly_1 | 18:28:19,943 INFO [org.wildfly.extension.undertow] (ServerService Thread Pool -- 47) JBAS017502: Undertow 1.1.0.Final starting mywildfly_1 | 18:28:19,943 INFO [org.wildfly.extension.undertow] (MSC service thread 1-15) JBAS017502: Undertow 1.1.0.Final starting mywildfly_1 | 18:28:19,969 INFO [org.jboss.as.connector.subsystems.datasources] (ServerService Thread Pool -- 27) JBAS010403: Deploying JDBC-compliant driver class org.h2.Driver (version 1.3) mywildfly_1 | 18:28:19,980 INFO [org.jboss.as.connector.deployers.jdbc] (MSC service thread 1-8) JBAS010417: Started Driver service with driver-name = h2 mywildfly_1 | 18:28:20,027 INFO [org.jboss.as.mail.extension] (MSC service thread 1-3) JBAS015400: Bound mail session mywildfly_1 | 18:28:20,027 INFO [org.jboss.as.naming] (MSC service thread 1-1) JBAS011802: Starting Naming Service mywildfly_1 | 18:28:20,139 INFO [org.jboss.as.connector.subsystems.datasources] (ServerService Thread Pool -- 27) JBAS010404: Deploying non-JDBC-compliant driver class com.mysql.jdbc.Driver (version 5.1) mywildfly_1 | 18:28:20,141 INFO [org.jboss.as.connector.deployers.jdbc] (MSC service thread 1-13) JBAS010417: Started Driver service with driver-name = mysql mywildfly_1 | 18:28:20,155 INFO [org.jboss.remoting] (MSC service thread 1-12) JBoss Remoting version 4.0.6.Final mywildfly_1 | 18:28:20,391 INFO [org.wildfly.extension.undertow] (ServerService Thread Pool -- 47) JBAS017527: Creating file handler for path /opt/jboss/wildfly/welcome-content mywildfly_1 | 18:28:20,408 INFO [org.wildfly.extension.undertow] (MSC service thread 1-14) JBAS017525: Started server default-server. mywildfly_1 | 18:28:20,429 INFO [org.wildfly.extension.undertow] (MSC service thread 1-14) JBAS017531: Host default-host starting mywildfly_1 | 18:28:20,560 INFO [org.wildfly.extension.undertow] (MSC service thread 1-4) JBAS017519: Undertow HTTP listener default listening on /0.0.0.0:8080 mywildfly_1 | 18:28:20,696 INFO [org.jboss.as.server.deployment.scanner] (MSC service thread 1-13) JBAS015012: Started FileSystemDeploymentService for directory /opt/jboss/wildfly/standalone/deployments mywildfly_1 | 18:28:20,697 INFO [org.jboss.as.server.deployment] (MSC service thread 1-16) JBAS015876: Starting deployment of "temp.war" (runtime-name: "temp.war") mywildfly_1 | 18:28:20,701 INFO [org.jboss.as.server.deployment] (MSC service thread 1-15) JBAS015876: Starting deployment of "employees.war" (runtime-name: "employees.war") mywildfly_1 | 18:28:20,719 INFO [org.jboss.as.connector.subsystems.datasources] (MSC service thread 1-4) JBAS010400: Bound data source mywildfly_1 | 18:28:20,720 INFO [org.jboss.as.connector.subsystems.datasources] (MSC service thread 1-2) JBAS010400: Bound data source mywildfly_1 | 18:28:20,815 INFO [org.jboss.as.jpa] (MSC service thread 1-6) JBAS011401: Read persistence.xml for MyPU mywildfly_1 | 18:28:20,867 INFO [org.jboss.as.jpa] (ServerService Thread Pool -- 50) JBAS011409: Starting Persistence Unit (phase 1 of 2) Service 'employees.war#MyPU' mywildfly_1 | 18:28:20,880 INFO [org.hibernate.jpa.internal.util.LogHelper] (ServerService Thread Pool -- 50) HHH000204: Processing PersistenceUnitInfo [ mywildfly_1 | name: MyPU mywildfly_1 | ...] mywildfly_1 | 18:28:20,959 INFO [org.jboss.ws.common.management] (MSC service thread 1-10) JBWS022052: Starting JBoss Web Services - Stack CXF Server 4.3.2.Final mywildfly_1 | 18:28:20,980 INFO [org.hibernate.Version] (ServerService Thread Pool -- 50) HHH000412: Hibernate Core {4.3.7.Final} mywildfly_1 | 18:28:20,984 INFO [org.hibernate.cfg.Environment] (ServerService Thread Pool -- 50) HHH000206: hibernate.properties not found mywildfly_1 | 18:28:20,986 INFO [org.hibernate.cfg.Environment] (ServerService Thread Pool -- 50) HHH000021: Bytecode provider name : javassist mywildfly_1 | 18:28:21,081 INFO [org.jboss.weld.deployer] (MSC service thread 1-9) JBAS016002: Processing weld deployment employees.war mywildfly_1 | 18:28:21,127 INFO [org.hibernate.validator.internal.util.Version] (MSC service thread 1-9) HV000001: Hibernate Validator 5.1.3.Final mywildfly_1 | 18:28:21,180 INFO [org.wildfly.extension.undertow] (MSC service thread 1-4) JBAS017534: Registered web context: /temp mywildfly_1 | 18:28:21,264 INFO [org.jboss.weld.deployer] (MSC service thread 1-13) JBAS016005: Starting Services for CDI deployment: employees.war mywildfly_1 | 18:28:21,298 INFO [org.jboss.weld.Version] (MSC service thread 1-13) WELD-000900: 2.2.6 (Final) mywildfly_1 | 18:28:21,310 INFO [org.jboss.weld.deployer] (MSC service thread 1-10) JBAS016008: Starting weld service for deployment employees.war mywildfly_1 | 18:28:21,452 INFO [org.jboss.as.jpa] (ServerService Thread Pool -- 50) JBAS011409: Starting Persistence Unit (phase 2 of 2) Service 'employees.war#MyPU' mywildfly_1 | 18:28:21,521 INFO [org.hibernate.annotations.common.Version] (ServerService Thread Pool -- 50) HCANN000001: Hibernate Commons Annotations {4.0.4.Final} mysqldb_1 | 2014-12-23 18:28:21 1 [Warning] IP address '172.17.0.5' could not be resolved: Name or service not known mywildfly_1 | 18:28:21,845 INFO [org.hibernate.dialect.Dialect] (ServerService Thread Pool -- 50) HHH000400: Using dialect: org.hibernate.dialect.MySQL5Dialect mywildfly_1 | 18:28:21,940 INFO [org.hibernate.hql.internal.ast.ASTQueryTranslatorFactory] (ServerService Thread Pool -- 50) HHH000397: Using ASTQueryTranslatorFactory mywildfly_1 | 18:28:22,276 INFO [org.hibernate.dialect.Dialect] (ServerService Thread Pool -- 50) HHH000400: Using dialect: org.hibernate.dialect.MySQL5Dialect mywildfly_1 | 18:28:22,282 INFO [stdout] (ServerService Thread Pool -- 50) Hibernate: drop table if exists EMPLOYEE_SCHEMA mywildfly_1 | 18:28:22,289 INFO [stdout] (ServerService Thread Pool -- 50) Hibernate: drop table if exists hibernate_sequence mywildfly_1 | 18:28:22,290 INFO [stdout] (ServerService Thread Pool -- 50) Hibernate: create table EMPLOYEE_SCHEMA (id integer not null, name varchar(40), primary key (id)) mywildfly_1 | 18:28:22,300 INFO [stdout] (ServerService Thread Pool -- 50) Hibernate: create table hibernate_sequence ( next_val bigint ) mywildfly_1 | 18:28:22,310 INFO [stdout] (ServerService Thread Pool -- 50) Hibernate: insert into hibernate_sequence values ( 1 ) mywildfly_1 | 18:28:22,312 INFO [stdout] (ServerService Thread Pool -- 50) Hibernate: INSERT INTO EMPLOYEE_SCHEMA(ID, NAME) VALUES (1, 'Penny') mywildfly_1 | 18:28:22,314 INFO [stdout] (ServerService Thread Pool -- 50) Hibernate: INSERT INTO EMPLOYEE_SCHEMA(ID, NAME) VALUES (2, 'Sheldon') mywildfly_1 | 18:28:22,317 INFO [stdout] (ServerService Thread Pool -- 50) Hibernate: INSERT INTO EMPLOYEE_SCHEMA(ID, NAME) VALUES (3, 'Amy') mywildfly_1 | 18:28:22,320 INFO [stdout] (ServerService Thread Pool -- 50) Hibernate: INSERT INTO EMPLOYEE_SCHEMA(ID, NAME) VALUES (4, 'Leonard') mywildfly_1 | 18:28:22,323 INFO [stdout] (ServerService Thread Pool -- 50) Hibernate: INSERT INTO EMPLOYEE_SCHEMA(ID, NAME) VALUES (5, 'Bernadette') mywildfly_1 | 18:28:22,324 INFO [stdout] (ServerService Thread Pool -- 50) Hibernate: INSERT INTO EMPLOYEE_SCHEMA(ID, NAME) VALUES (6, 'Raj') mywildfly_1 | 18:28:22,328 INFO [stdout] (ServerService Thread Pool -- 50) Hibernate: INSERT INTO EMPLOYEE_SCHEMA(ID, NAME) VALUES (7, 'Howard') mywildfly_1 | 18:28:22,330 INFO [stdout] (ServerService Thread Pool -- 50) Hibernate: INSERT INTO EMPLOYEE_SCHEMA(ID, NAME) VALUES (8, 'Priya') mywildfly_1 | 18:28:23,361 INFO [org.jboss.resteasy.spi.ResteasyDeployment] (MSC service thread 1-1) Deploying javax.ws.rs.core.Application: class org.javaee7.samples.employees.MyApplication mywildfly_1 | 18:28:23,396 INFO [org.wildfly.extension.undertow] (MSC service thread 1-1) JBAS017534: Registered web context: /employees mywildfly_1 | 18:28:23,433 INFO [org.jboss.as.server] (ServerService Thread Pool -- 28) JBAS018559: Deployed "employees.war" (runtime-name : "employees.war") mywildfly_1 | 18:28:23,434 INFO [org.jboss.as.server] (ServerService Thread Pool -- 28) JBAS018559: Deployed "temp.war" (runtime-name : "temp.war") mywildfly_1 | 18:28:23,452 INFO [org.jboss.as] (Controller Boot Thread) JBAS015961: Http management interface listening on http://127.0.0.1:9990/management mywildfly_1 | 18:28:23,453 INFO [org.jboss.as] (Controller Boot Thread) JBAS015951: Admin console listening on http://127.0.0.1:9990 mywildfly_1 | 18:28:23,453 INFO [org.jboss.as] (Controller Boot Thread) JBAS015874: WildFly 8.2.0.Final "Tweek" started in 5330ms - Started 344 of 404 services (102 services are lazy, passive or on-demand) mywildfly_1 | 18:28:30,954 INFO [stdout] (default task-1) Hibernate: select employee0_.id as id1_0_, employee0_.name as name2_0_ from EMPLOYEE_SCHEMA employee0_Find out the IP address using boot2docker ip and access the app as: curl http://192.168.59.103:8080/employees/resources/employees <?xml version="1.0" encoding="UTF-8" standalone="yes"?><collection><employee><id>1</id><name>Penny</name></employee><employee><id>2</id><name>Sheldon</name></employee><employee><id>3</id><name>Amy</name></employee><employee><id>4</id><name>Leonard</name></employee><employee><id>5</id><name>Bernadette</name></employee><employee><id>6</id><name>Raj</name></employee><employee><id>7</id><name>Howard</name></employee><employee><id>8</id><name>Priya</name></employee></collection>Complete list of Fig commands can be seen by typing fig: Commands: build Build or rebuild services help Get help on a command kill Kill containers logs View output from containers port Print the public port for a port binding ps List containers pull Pulls service images rm Remove stopped containers run Run a one-off command scale Set number of containers for a service start Start services stop Stop services restart Restart services up Create and start containers Particularly interesting is scale command, and we’ll take a look at it in a subsequent blog. File issues on github. Enjoy!Reference: Docker orchestration using Fig from our JCG partner Arun Gupta at the Miles to go 2.0 … blog....
java-logo

Java 8 Stream and Lambda Expressions – Parsing File Example

Recently I wanted to extract certain data from an output log. Here’s part of the log file:                   2015-01-06 11:33:03 b.s.d.task [INFO] Emitting: eVentToRequestsBolt __ack_ack [-6722594615019711369 -1335723027906100557] 2015-01-06 11:33:03 c.s.p.d.PackagesProvider [INFO] ===---> Loaded package com.foo.bar 2015-01-06 11:33:04 b.s.d.executor [INFO] Processing received message source: eventToManageBolt:2, stream: __ack_ack, id: {}, [-6722594615019711369 -1335723027906100557] 2015-01-06 11:33:04 c.s.p.d.PackagesProvider [INFO] ===---> Loaded package co.il.boo 2015-01-06 11:33:04 c.s.p.d.PackagesProvider [INFO] ===---> Loaded package dot.org.biz I decided to do it using the Java8 Stream and Lambda Expression features. Read the file First, I needed to read the log file and put the lines in a Stream: Stream<String> lines = Files.lines(Paths.get(args[1])); Filter relevant lines I needed to get the packages names and write them into another file. Not all lines contained the data I need, hence filter only relevant ones. lines.filter(line -> line.contains("===---> Loaded package")) Parsing the relevant lines Then, I needed to parse the relevant lines. I did it by first splitting each line to an array of Strings and then taking the last element in that array. In other words, I did a double mapping. First a line to an array and then an array to a String. .map(line -> line.split(" ")) .map(arr -> arr[arr.length - 1]) Writing to output file The last part was taking each string and write it to a file. That was the terminal operation. .forEach(package -> writeToFile(fw, package)); writeToFile is a method I created. The reason is that Java File System throws IOException. You can’t use checked exceptions in lambda expressions. Here’s a full example (note, I don’t check input) import java.io.FileWriter; import java.io.IOException; import java.nio.file.Files; import java.nio.file.Paths; import java.util.Arrays; import java.util.List; import java.util.stream.Stream;public class App { public static void main(String[] args) throws IOException { Stream<String> lines = null; if (args.length == 2) { lines = Files.lines(Paths.get(args[1])); } else { String s1 = "2015-01-06 11:33:03 b.s.d.task [INFO] Emitting: adEventToRequestsBolt __ack_ack [-6722594615019711369 -1335723027906100557]"; String s2 = "2015-01-06 11:33:03 b.s.d.executor [INFO] Processing received message source: eventToManageBolt:2, stream: __ack_ack, id: {}, [-6722594615019711369 -1335723027906100557]"; String s3 = "2015-01-06 11:33:04 c.s.p.d.PackagesProvider [INFO] ===---> Loaded package com.foo.bar"; String s4 = "2015-01-06 11:33:04 c.s.p.d.PackagesProvider [INFO] ===---> Loaded package co.il.boo"; String s5 = "2015-01-06 11:33:04 c.s.p.d.PackagesProvider [INFO] ===---> Loaded package dot.org.biz"; List<String> rows = Arrays.asList(s1, s2, s3, s4, s5); lines = rows.stream(); } new App().parse(lines, args[0]);} private void parse(Stream<String> lines, String output) throws IOException { final FileWriter fw = new FileWriter(output); //@formatter:off lines.filter(line -> line.contains("===---> Loaded package")) .map(line -> line.split(" ")) .map(arr -> arr[arr.length - 1]) .forEach(package -> writeToFile(fw, package)); //@formatter:on fw.close(); lines.close(); }private void writeToFile(FileWriter fw, String package) { try { fw.write(String.format("%s%n", package)); } catch (IOException e) { throw new RuntimeException(e); } }}Reference: Java 8 Stream and Lambda Expressions – Parsing File Example from our JCG partner Eyal Golan at the Learning and Improving as a Craftsman Developer blog....
software-development-2-logo

Breaking Bad … interfaces.

A question of efficiency. So, you start working on some code and a monstrous interface snarls back at you, picking from its teeth pieces of the previous programmer who dared approach. It has twenty-five methods, and you just need to add one more teeny-weeny method to it. Should you clench and add it, or should you listen to that voice telling you that it’s time to refactor? The Interface Segregation Principle says that you should hack that beast into an interface-salad but deadlines loom and managers would never understand. How can you quickly see which subset of interfaces you should choose? Two approaches exist: the semantic and the syntactic. Semantically, a programmer smashes a large interface into smaller ones by examining each method’s purpose, identifying which methods, “Belong,” together and creating interfaces based on these commonalities. Make no mistake: this is the best strategy. The only problem with this approach is that different programmers evaluate different commonalities differently. Ask six programmers to split a large interface and you might find six different decompositions. The other is the syntactic approach. Whereas semantics concerns meaning, syntactics removes all meaning and examines only the brute fact of relationship between client and interface method. Semantic concepts live in the head of the programmer, subjective; syntactic concepts live in the source code, objective. Being objective, a syntactic approach should allow an objective evaluation of just how, “Bad,” an interface is before surgery, and just how, “Good,” the patients(?) are afterwards. Just for fun, let’s attempt such an evaluation. The ISP says that, “No client should be forced to depend on methods it does not use. ISP splits interfaces which are very large into smaller and more specific ones so that clients will only have to know about the methods that are of interest to them.” So consider figure 1, showing a client class, ClientA, and its three dependencies on interface I‘s five methods.Is interface I bad? Well, the interface exposes ClientA to three methods that it does use and to two methods that it does not. Perhaps the question is not whether the ISP is violated but to what degree. Might we therefore ask how efficiently the interface I is used by its clients? Let’s define that the efficiency of a client’s use of an interface is the number of methods that the client calls on the interface divided by the total number of methods in that interface, expressed as a percentage. So as ClientA uses only 3/5ths of interface I we can say that interface I is 60% efficient with respect to that client. And what if two clients nibble on the interface? See figure 2.Figure 2 adds a second class, ClientB, which depends on four of interface I‘s method, giving it a usage efficiency of 80%. The overall efficiency of I in this case is the sum of both efficiencies divided by the number of clients: (60% + 80%) / 2 = 70%. Of course, we can define such arithmetic acrobatics any way we like, but this model of interface efficiency tries to capture the interesting aspects. As, “No client should be forced to depend on methods it does not use,” then we would like our interface efficiency to fall as interfaces grow and clients depend on relatively fewer methods (which it does), and we would like it to rise as interfaces shrink and clients depend on relatively more methods (which it does). And with an objective criterion, we can have machines do the work for us, bundling the calculations into an algorithm and stuffing it into a code analyzer so that it might sniff out the least efficient interfaces in our systems. How might we use such an algorithm? We could make a few educated guesses, splitting a large interface into smaller ones, having our algorithm calculate the before and after efficiencies, and proposing those splits with the highest efficiencies. But we can be even lazier. An interface has a low efficiency because one or more of its clients depends on too few of its methods; so what if we have our algorithm scan all clients of our interface, hypothetically extract from the interface the methods each client calls, and then predict the efficiency of the remaining interface? This might help identify which subsets of methods in the interface, “Belong,” together as the extracted interfaces reflect not a programmer’s notion of commonality but actual client use. We could then extract those methods that give the original interface the best efficiency gain and start the process again. But we can be even lazier. What if we tell our algorithm, “Listen, don’t just give me a list of potential interface extractions, but simulate the extraction of the most efficient and then repeat the process on that remaining interface, cumulatively predicting a path that makes the original interface increasingly efficient. And keep going until there’s nothing left to extract. And be quick about it, the day’s gettin’ old.” This would then provide us not just with a suggestion of an interface to extract but a full roadmap of extractions that lead to a distant but high efficiency. Of course, we would not then blindly follow this roadmap: semantic decomposition trumps all. These syntactic suggestions might, however, help us evaluate our choice. If we find that they support our fine commonality guesses, so much the better. Puddings’n’proof. Let’s try it out. Let’s take some honest hard-working Java code and pour it into the algorithm to see what oozes out. (Spoiklin Soice has been updated with the algorithm: right click on a class and select, “Suggest extraction”.) As usual, the most recent structural investigation – presently, FitNesse – will provide grist for the analytic mills. FitNesse’s average interface efficiency is impressively high. Interfaces tend to be small and finding large inefficient interfaces proves difficult, but we do find a candidate in interface WikiPage. WikiPage has 19 methods (so is not too obese) and is only 15% efficient, partly because of the huge number of clients, 104, few of which call all of its methods. The list below presents these methods, along with their percentage use (yes, you can calculate that, too, from the model): getPageCrawler: 68.3% getData: 61.5% getName: 32.7% commit: 23.1% getParent: 15.4% getChildren: 12.5% getChildPage: 9.6% addChildPage: 8.7% getExtension: 7.7% hasExtension: 6.7% getDataVersion: 5.8% getHelpText: 5.8% removeChildPage: 5.8% hasChildPage: 5.8% getActions: 4.8% getParentForVariables: 4.8% setParentForVariables: 3.8% getHeaderPage: 3.8% getFooterPage: 3.8% Take a moment: based on whatever meaning you care to take from these names, how would you split this interface? If we have our algorithm plot a road-map of extractions, it suggests that the extraction which will raise this interface’s efficiency highest (to 24%) is the following: addChildPage getPageCrawler commit getData getParent hasChildPage getName getChildren removeChildPage A perfect semantic decomposition would have produced an extracted interface all of whose methods would share some obvious commonality and the above is no such decomposition. That commit() seems a little odd, for instance. Nevertheless our semantic brethren may not be too displeased with this overall suggestion: it seems heavy on “child” and “parent”, and semanticians like that sort of thing. If we had guessed to break out a smaller interface to focus on relationships, then the above might offer some validation. Moving on, the algorithm next suggests the following interface extraction, bringing the remaining methods’ efficiency to a whopping 63%: getActions setParentForVariables getHelpText getHeaderPage getChildPage getParentForVariables getFooterPage Again, the beefy rugged setParentForVariables() method looks like it’s wandered into the perfume department of the store, but the suggestion seems quite “page”-heavy. Whereas the first interface also dealt with pages – the donor is WikiPage after all – this interface seems less concerned with relationships and more on page mechanics: headers, footers, help-text and actions, for example. So once more it may offer some consolation had we initially thought to extract an interface based on web-page details. The final suggested extraction to bring us to 100% efficiency is the delightful: getExtension hasExtension A more coherent interface we could not wish for. Indeed, that a purely syntactic algorithm can unearth so semantically coherent an interface hints at careful thought having been put into FitNesse’s interface’s design. You get the point, though a further example is available here, and some of Spoiklin’s own dirty laundry is here (oh, the shame!). Summary. Machines cannot design good, small, efficient interfaces for us – algorithms do not understand the methods they scrutinize – but they can offer a client-use statistical perspective. If algorithms happen to suggest an interface extraction that meets approval, this only reflects that the designers of the original interface had a good idea of how clients would use various parts of it, if not the whole. Programmers are sailors. They sail not calm tropical seas but frozen arctic oceans, their ships surrounded by an ever-shifting ice-pack, in which the primary competing forces – those of functionality-delivery and structural maintenance – threaten daily to crush their hulls. They discard no navigational tools, no matter how inconsequential. </purple> Notes. Slightly more formally: given a set of n interfaces where the ith interface is Ii and a set of m client classes, and given that the number of methods in the ith interface is |Ii| and the number of client classes of ith interface is |Ci| and the number of methods that the jth client depends on in the ith interface is given by |Uji|, then the efficiency of the n interfaces is given by:Also, the algorithm needs a few more constraints than just this equation: for example, we don’t want it to pull out too many single-method interfaces, which are 100% efficient but a little … overkill. Nevertheless, the above equation remains key.Reference: Breaking Bad … interfaces. from our JCG partner Edmund Kirwan at the A blog about software. blog....
java-logo

JavaFX List Example

This is an example list application built using JavaFX. The app is a list of todo (to do) items. This app has functions to add, update and delete items in the list.  The list data is stored in HSQLDB relational database. The app accesses the database using JDBC (Java Database Connectivity) API. The app is packaged as an executable JAR file. JavaFX 2.2, Java SE 7 and HSQLDB 2.3.2 are used to build the app.         This article explains building the app in detail. This document’s contents:Table Of Contents1. Install HSQL Database1.1. About HSQLDB 1.2. Download Database2. Create App Database and Table2.1. Create Todos Database 2.2. Create Todo Table3. The Application3.1. Application Classes4. Build the GUI4.1. The Code 4.2. Code Description 4.3. Source Code5. Create Database Access Code5.1. Get Connection 5.2. Get All Rows 5.3. Insert a Row 5.4. Check if Todo Name Exists 5.5. Delete a Row 5.6. Update a Row 5.7. Close Database 5.8. Source Code6. Wire GUI with Database Access6.1. Coding 6.2. Create a New Todo 6.3. Save a Todo 6.4. Delete or Cancel a Todo 6.5. App Start and Close 6.6. Source Code7. Deploy as a JAR File7.1. Create Executable JAR File: todoapp.jar 7.2. Run the App8. Download Java Source Code  1. Install HSQL Database 1.1. About HSQLDB The HSQL relational database is used for storing the todo data. In this section – get and install the database. HSQLDB (HyperSQL DataBase) is the SQL relational database software written in Java and runs in a JVM. It is a small, fast multithreaded and transactional database engine with in-memory and disk-based tables and supports embedded and server modes. This includes a JDBC driver. 1.2. Download Database Download the database software from the download link on the website http://hsqldb.org/. In this case, the HSQLDB version 2.3.2 is downloaded. The downloaded file is a ZIP file. Extract the ZIP file into any directory of your choice. The ZIP file is extracted into a folder hsqldb-2.3.2\hsqldb. This is the home (or install) directory. This completes the installation. The installed database has user documentation, JDBC driver, database executables and utility programs. The install directory has /doc and /lib directories (in addition to others). The /doc directory has the user guides. The /lib directory has the following JAR files used commonly:hsqldb.jar:  This has the database engine, JDBC driver and a GUI database access tool. sqltool.jar: This has a SQL command line database access tool.2. Create App Database and Table 2.1. Create Todos Database The GUI database access tool is used to create and access the database. From the DOS command prompt run this: > java -cp "X:\JCG\articles\A JavaFX List Example\hsqldb-2.3.2\hsqldb\lib\hsqldb.jar" org.hsqldb.util.DatabaseManagerSwing NOTE: The hsqldb.jar file is to be in the classpath. This opens a Connect GUI dialog as shown below.Enter the following information into the dialog:Recent Setting: <Do not select anything now. Next time to connect to the database select the setting created now.> Setting Name: <enter a name> todo db setting Type: <select> HSQL Database Engine Standalone Driver: <select> hsqldb.jdbcDriver URL: <enter database file path> jdbc:hsqldb:file:<<filepath – see note below for more details to specify the path>> User: <leave blank> Password: <leave blank>Note on URL’s filepath: The filepath can be specified as a relative or an absolute path. The relative path is relative to the current directory; for example jdbc:hsqldb:file:db\TODOS_DB in the URL creates a directory called db and the TODOS_DB database in it. An example with absolute path is jdbc:hsqldb:file:X:\JCG\articles\A JavaFX List Example\db\TODOS_DB. Click Ok. This creates a database named TODOS_DB in the specified directory. This also opens the HSQLDatabase Manager window. The window has areas showing the database structure, SQL entry and result details. The window is shown below.2.2 Create Todo Table The todo table has three columns: id, name and description.id: This is a unique integer generated by the database system. This is defined as an IDENTITY column.An IDENTITY column is an INTEGER auto-generated by the database’s sequence generator. By default the column values start from 1 and are incremented by 1. When an insert is made into the table, the id column value is automatically populated with a new sequence number. The syntax for inserting and retrieving the id column value are shown later in this article (see section 5. Create Database Access Code).name: This is defined as VARCHAR (50), and not null. description: This is defined as VARCHAR(500).In the HSQLDatabase Manager window enter the following SQL script and execute it. CREATE TABLE TODO_TABLE ( id INTEGER GENERATED BY DEFAULT AS IDENTITY, name VARCHAR(50) NOT NULL, description VARCHAR(500) ); This creates the todo table. The newly created table can be viewed in the database structure area. NOTE: This step need to be completed before going further. The app’s code assumes that the database and the table are created. 3. The Application The todos are displayed in a list, where each todo is a list item. When a todo is selected in the list the name and description are displayed in a text box and text area respectively. This data can be edited. There are buttons to create a todo, delete and save. A status message shows the recent action performed. The GUI is displayed in a window. The data displayed in the list and text box/area is accessed from the todo database. The database is opened on app start and closed on closing the app. The following shows the completed app’s GUI.3.1. Application Classes The app comprises three Java classes.Todo.java: This class represents the todo item. TodoApp.java: This class is the main application with GUI and program execution logic. TodoDataAccess.java: This class has functions to access the todo database.3.1.1 Todo.java A todo is represented by the Todo.java class. A todo has name and description properties. This also maintains a unique id field. 3.1.2 TodoDataAccess.java This class has functions to access the todo database and the data. Its functions are:Connect to and close the database Insert, update, delete, query and validate data in the database3.1.3 TodoApp.java This class is the main application program. This has functions to start the app, close it, create the user interface and wire the GUI and the app to the data access code. 4. Build the GUI In this step the GUI is constructed without the database access and action event handlers for the buttons. Only, the list is wired to a list selection change listener. The app displays some predefined todo data in the list. The list todo items can be selected and the corresponding todo name and description are displayed in their respective text box/area. The following shows the TodoApp.java class’s code followed by its description. 4.1.The Code TodoApp.java: import javafx.application.Application; import javafx.stage.Stage; import javafx.scene.Scene; import javafx.scene.layout.GridPane; import javafx.scene.layout.HBox; import javafx.scene.layout.VBox; import javafx.scene.layout.AnchorPane; import javafx.scene.text.Font; import javafx.scene.text.FontWeight; import javafx.scene.text.Text; import javafx.scene.paint.Color; import javafx.scene.control.ListView; import javafx.scene.control.Label; import javafx.scene.control.TextField; import javafx.scene.control.TextArea; import javafx.scene.control.ScrollPane; import javafx.scene.control.ScrollPane.ScrollBarPolicy; import javafx.scene.control.Button; import javafx.scene.control.Tooltip; import javafx.scene.text.Text; import javafx.geometry.Pos; import javafx.geometry.Insets; import javafx.collections.FXCollections; import javafx.collections.ObservableList; import java.util.List; import java.util.ArrayList; import javafx.beans.value.ChangeListener; import javafx.beans.value.ObservableValue;public class TodoApp extends Application { private ListView<Todo> listView; private ObservableList<Todo> data; private TextField nametxt; private TextArea desctxt; private Text actionstatus;public static void main(String [] args) { Application.launch(args); }@Override public void start(Stage primaryStage) { primaryStage.setTitle("Todo App - version 1");// gridPane layout GridPane grid = new GridPane(); grid.setAlignment(Pos.CENTER); grid.setHgap(15); grid.setVgap(20); grid.setPadding(new Insets(25, 25, 25, 25)); // list view, listener and list data listView = new ListView<>(); listView.getSelectionModel().selectedIndexProperty().addListener( new ListSelectChangeListener()); data = getListData(); listView.setItems(data); grid.add(listView, 1, 1); // col = 1, row = 1 // todo name label and text fld - in a hbox Label namelbl = new Label("Todo Name:"); nametxt = new TextField(); nametxt.setMinHeight(30.0); nametxt.setPromptText("Enter todo name (required)."); nametxt.setPrefColumnCount(20); nametxt.setTooltip(new Tooltip( "Item name (5 to 50 chars length)")); HBox hbox = new HBox(); hbox.setSpacing(10); hbox.getChildren().addAll(namelbl, nametxt);// todo desc text area in a scrollpane desctxt = new TextArea(); desctxt.setPromptText("Enter description (optional)."); desctxt.setWrapText(true); ScrollPane sp = new ScrollPane(); sp.setContent(desctxt); sp.setFitToWidth(true); sp.setFitToHeight(true); sp.setPrefHeight(300); sp.setHbarPolicy(ScrollPane.ScrollBarPolicy.NEVER); sp.setVbarPolicy(ScrollPane.ScrollBarPolicy.AS_NEEDED); // todo hbox (label + text fld), scrollpane - in a vbox VBox vbox = new VBox(); vbox.setSpacing(10); vbox.getChildren().addAll(hbox, sp);grid.add(vbox, 2, 1); // col = 2, row = 1 // new and delete buttons Button newbtn = new Button("New"); Button delbtn = new Button("Delete"); HBox hbox2 = new HBox(10); hbox2.getChildren().addAll(newbtn, delbtn); grid.add(hbox2, 1, 2); // col = 1, row = 2// save button to the right anchor pane and grid Button savebtn = new Button("Save"); AnchorPane anchor = new AnchorPane(); AnchorPane.setRightAnchor(savebtn, 0.0); anchor.getChildren().add(savebtn); grid.add(anchor, 2, 2); // col = 2, row = 2// action message (status) text actionstatus = new Text(); actionstatus.setFill(Color.FIREBRICK); actionstatus.setText(""); grid.add(actionstatus, 1, 3); // col = 1, row = 3// scene Scene scene = new Scene(grid, 750, 400); // width=750, height=400 primaryStage.setScene(scene); primaryStage.show(); // initial selection; statement does nothing if no data listView.getSelectionModel().selectFirst(); } // start()private class ListSelectChangeListener implements ChangeListener<Number> { @Override public void changed(ObservableValue<? extends Number> ov, Number old_val, Number new_val) { if ((new_val.intValue() < 0) || (new_val.intValue() >= data.size())) { return; // invalid data } // set name and desc fields for the selected todo Todo todo = data.get(new_val.intValue()); nametxt.setText(todo.getName()); desctxt.setText(todo.getDesc()); actionstatus.setText(todo.getName() + " - selected"); } }private ObservableList<Todo> getListData() { List<Todo> list = new ArrayList<>(); // initial list data list.add(new Todo("Work", "Work on JCG's example article.")); list.add(new Todo("Grocery", "Get apples, milk and bread.")); list.add(new Todo("Calls", "Call kid brother.")); list.add(new Todo("Read book", "Magnificent Obcession, by Lloyd C. Douglas.")); ObservableList<Todo> data = FXCollections.observableList(list); return data; } } 4.2. Code Description 4.2.1 JavaFX Classes The following describes the JavaFX classes used to build the GUI:The Stage class is used to construct the main window of the app. The GridPane is used to layout the controls (buttons, text fields etc.) in a grid of rows and columns. The HBox and VBox lay out its child controls in a single horizontal or vertical row respectively. The ListView is used to display a vertical scrollable list of todo items from which the user can select. The Label and Text are used for the todo name label and text fields. The TextArea is used for the todo description field. The field is placed in a ScrollPane, so that the text can be scrolled. The Button control is used for the new, save and delete buttons. The Text is used to display the action status.4.2.2 Layout of Controls The grid pane layout has 3 rows and 2 columns. The cell in which the controls are placed is as follows:Row 1 col 1 has the list view. Todo label and text field are placed in hbox. Row 1 col 2 has the hbox and the todo description text area – in a vbox. Row 2 col 1 has the new and delete buttons – in an hbox. Row 2 col 2 has the save button. Row 3 col 1 has the status text.4.2.3 List’s Change Listener A list selection change listener, of the type ChangeListener<Number> is attached to the list view: listView.getSelectionModel().selectedIndexProperty().addListener(new changeListener()); When a list item is selected, the item’s todo name and description are displayed in the text fields. 4.2.4 List’s Data The list view is populated with data from an ObservableList<Todo> collection – in the app’s start() method: data = getListData();listView.setItems(data); In this section, the list’s data is created within the program. The getListData() method creates todos and returns them as ObservableList<Todo> collection. 4.3 Source Code This is the version 1 of the app. Two classes are newly created. The classes are:Todo.java TodoApp.javaNOTE: To compile the code and run the app, the jfxrt.jar (JavaFX  library) file must be in the classpath. For Java 7 this can be found at: <JRE_HOME>/lib/jfxrt.jar. 5. Create Database Access Code The todo list’s data is stored and accessed from a database. The TODO_TABLE in the TODO_DB database stores the todo details. The database and the table are already created earlier (see section 2. Create App Database and Table). Note the app assumes that the database is created before accessing it. This section describes the database access code. The TodoDataAccess.java class has the code. This code uses JDBC (Java Database Connectivity) API to access the TODO_DB database. NOTE: The app’s GUI is wired to the database access in the next section (6. Wire GUI with Database Access). This class has methods to:Connect to the todo database Close the todo database Read all todo table rows into a List collection Insert a row into todo table Check if a todo name exists in the todo table Delete a row from the todo table Update a row in the todo tableThe following shows the TodoDataAccess.java class’s code and details. 5.1 Get Connection The constructor has code to access the database and gets the Connection object. This connection object is used to read or update database data. The connection’s properties are set as auto commit, i.e., a transaction commits at insert, update or delete without an explicit commit. The connection is of updateable type. The DriverManager's getConnection() static method uses a URL to connect to the database. public TodoDataAccess() throws SQLException, ClassNotFoundException { Class.forName("org.hsqldb.jdbc.JDBCDriver" ); conn = DriverManager.getConnection( "jdbc:hsqldb:file:db/TODOS_DB;ifexists=true;shutdown=true", "", ""); conn.setAutoCommit(true); conn.setReadOnly(false); } 5.2 Get All Rows This method retrieves all rows from todo table and returns a List collection of Todo elements. public List<Todo> getAllRows() throws SQLException { String sql = "SELECT * FROM " + todoTable + " ORDER BY name"; PreparedStatement pstmnt = conn.prepareStatement(sql); ResultSet rs = pstmnt.executeQuery(); List<Todo> list = new ArrayList<>(); while (rs.next()) { int i = rs.getInt("id"); String s1 = rs.getString("name"); String s2 = rs.getString("desc"); list.add(new Todo(i, s1, s2)); } pstmnt.close(); // also closes related result set return list; } 5.3 Insert a Row This method inserts a row into the todo table. The method returns an id for the new todo row. The id value is a sequence number generated by the database system. This is an IDENTITY column. The DEFAULT keyword (in the INSERT statement) is used for the IDENTITY column, which results in an auto-generated value for the column. See section 2.2. Create Todo Table for details on IDENTITY column creation. The PreparedStatement's getGeneratedKeys() method retrieves a ResultSet with the newly generated identity column value. public int insertRow(Todo todo) throws SQLException { String dml = "INSERT INTO " + todoTable + " VALUES (DEFAULT, ?, ?)"; PreparedStatement pstmnt = conn.prepareStatement(dml, PreparedStatement.RETURN_GENERATED_KEYS); pstmnt.setString(1, todo.getName()); pstmnt.setString(2, todo.getDesc()); pstmnt.executeUpdate(); // returns insert count // get identity column value ResultSet rs = pstmnt.getGeneratedKeys(); rs.next(); int id = rs.getInt(1); pstmnt.close(); return id; } 5.4 Check if Todo Name Exists This method checks if a todo name already exists in the todo table. Note the app allows only unique todo names. public boolean nameExists(Todo todo) throws SQLException { String sql = "SELECT COUNT(id) FROM " + todoTable + " WHERE name = ? AND id <> ?"; PreparedStatement pstmnt = conn.prepareStatement(sql); pstmnt.setString(1, todo.getName()); pstmnt.setInt(2, todo.getId()); ResultSet rs = pstmnt.executeQuery(); rs.next(); int count = rs.getInt(1); pstmnt.close(); if (count > 0) { return true; } return false; } 5.5 Delete a Row This method deletes a row from the todo table for a given todo, if it exists. Note that no exception is thrown if no row is deleted. public void deleteRow(Todo todo) throws SQLException { String dml = "DELETE FROM " + todoTable + " WHERE id = ?"; PreparedStatement pstmnt = conn.prepareStatement(dml); pstmnt.setInt(1, todo.getId()); pstmnt.executeUpdate(); // returns delete count (0 for none) pstmnt.close(); } 5.6 Update a Row This method updates an existing row in the todo table with any changes to the todo’s properties. public void updateRow(Todo todo) throws SQLException { String dml = "UPDATE " + todoTable + " SET name = ?, desc = ? " + " WHERE id = ?"; PreparedStatement pstmnt = conn.prepareStatement(dml); pstmnt.setString(1, todo.getName()); pstmnt.setString(2, todo.getDesc()); pstmnt.setInt(3, todo.getId()); pstmnt.executeUpdate(); // returns update count pstmnt.close(); } 5.7 Close Database This method closes the database connection and shutdowns the database. public void closeDb() throws SQLException { conn.close(); } 5.8 Source Code This is the version 2 of the app. One class is newly created – TodoDataAccess.java. There are no changes to the others. The classes are:Todo.java TodoDataAccess.javaNOTE: The classes are compiled. There is no program to run. 6. Wire GUI with Database Access This is the completed app. The app’s GUI is wired to the database. The app is updated to have the following functions: Add a new todo item to the list.Click the new button; enter todo name and description fields. Click the save button. This inserts the newly entered todo into the database. The new todo item is added to the list. The app validates that the entered todo name has 5 to 50 character length and is unique in the list. While entering the new todo, the entry can be cancelled by clicking the delete button.Update a todo item in the list.Select a todo from the list. Edit the name and/or description fields. Click the save button. This saves the updated todo in the database and updates the list, after validation.Delete a todo item in the list.Select a todo item from the list. Click the delete button. This deletes the todo from the database and the list.App start and close.At the app start all the todos in the database are loaded into the list. At the close of the app the database is closed.6.1 Coding In this section the app is updated:The new, save and delete buttons are wired to the respective event handler. The handler’s code accesses the database. The app start and close methods access the database.The database access code is already built in the previous section (5. Create Database Access Code). 6.1.1 About Event Handler An event handler of type ActionEvent is used as a button’s action event handler. The interface EventHandler is implemented for this purpose. The button’s handler property is set as button.setOnaction(someHandler). This is common for the three buttons in this app – new, delete and save. 6.2 Create a New Todo When a user clicks the new button, a new todo item is created in the list view, and the app prompts the user to enter new todo’s name and description. private class NewButtonListener implements EventHandler<ActionEvent> { @Override public void handle(ActionEvent e) { actionstatus.setText("New"); // creates a todo at first row with name NEW todo and // selects it Todo todo = new Todo(0, "NEW Todo", ""); // 0 = dummy id int ix = 0; data.add(ix, todo); listView.getSelectionModel().clearAndSelect(ix); nametxt.clear(); desctxt.clear(); nametxt.setText("NEW Todo"); nametxt.requestFocus(); } } 6.3 Save a Todo When the save button is clicked, the app:Validates the todo name for its length (5 to 50 characters) Checks if the name already exists in the database Inserts the todo into the databaseNote that this event handler is used for both the insert and update functions. private class SaveButtonListener implements EventHandler<ActionEvent> { @Override public void handle(ActionEvent ae) { int ix = listView.getSelectionModel().getSelectedIndex(); if (ix < 0) { // no data selected or no data return; } String s1 = nametxt.getText(); String s2 = desctxt.getText(); // validate name if ((s1.length() < 5) || (s1.length() > 50)) { actionstatus.setText( "Name must be 5 to 50 characters in length"); nametxt.requestFocus(); nametxt.selectAll(); return; } // check if name is unique Todo todo = data.get(ix); todo.setName(s1); todo.setDesc(s2); if (isNameAlreadyInDb(todo)) { actionstatus.setText("Name must be unique!"); nametxt.requestFocus(); return; } if (todo.getId() == 0) { // insert in db (new todo) int id = 0; try { id = dbaccess.insertRow(todo); } catch (Exception e) { displayException(e); } todo.setId(id); data.set(ix, todo); actionstatus.setText("Saved (inserted)"); } else { // db update (existing todo) try { dbaccess.updateRow(todo); } catch (Exception e) { displayException(e); } actionstatus.setText("Saved (updated)"); } // end-if, insert or update in db // update list view with todo name, and select it data.set(ix, null); // required for refresh data.set(ix, todo); listView.getSelectionModel().clearAndSelect(ix); listView.requestFocus(); } }private boolean isNameAlreadyInDb(Todo todo) { boolean bool = false; try { bool = dbaccess.nameExists(todo); } catch (Exception e) { displayException(e); } return bool; } 6.4 Delete or Cancel a Todo The delete button’s action serves two functions:Cancels a new todo that is being entered, and not yet saved. Deletes a selected (existing) todo item from the list and the database.private class DeleteButtonListener implements EventHandler<ActionEvent> { @Override public void handle(ActionEvent ae) { int ix = listView.getSelectionModel().getSelectedIndex(); if (ix < 0) { // no data or none selected return; } Todo todo = data.remove(ix); try { dbaccess.deleteRow(todo); } catch (Exception e) { displayException(e); } actionstatus.setText("Deleted"); // set next todo item after delete if (data.size() == 0) { nametxt.clear(); desctxt.clear(); return; // no selection } ix = ix - 1; if (ix < 0) { ix = 0; } listView.getSelectionModel().clearAndSelect(ix); // selected ix data (not set by list listener); // requires this is set Todo itemSelected = data.get(ix); nametxt.setText(itemSelected.getName()); desctxt.setText(itemSelected.getDesc()); listView.requestFocus(); } } 6.5 App Start and Close The JavaFX Application class’s init() and stop() methods are used for app’s initialization and closing. These are overridden in the app. The init method has code to access the database at app start. The stop method has code to close the database at the closing of the app. Also, following the app start, the todo list is populated with database data (instead of the data created within the program in the earlier version 1). This replaces the code from the version 1. The start method’s code data = getListData() is replaced with data = getDbData(). @Override public void init() { try { dbaccess = new TodoDataAccess(); } catch (Exception e) { displayException(e); } } @Override public void stop() { try { dbaccess.closeDb(); } catch (Exception e) { displayException(e); } } private ObservableList<Todo> getDbData() { List<Todo> list = null; try { list = dbaccess.getAllRows(); } catch (Exception e) { displayException(e); } ObservableList<Todo> dbData = FXCollections.observableList(list); return dbData; } @Override public void start(Stage primaryStage) { ... data = getDbData(); listView.setItems(data); ... 6.6 Source Code This is the version 3 of the app, and is the final. One class, TodoApp.java, is modified. There are no changes to the others. The classes are:Todo.java TodoDataAccess.java TodoApp.javaNOTE:To compile the app, the jfxrt.jar must be in the classpath. To run the app, jfxrt.jar and the hsqldb.jar files must be in the classpath.7. Deploy as a JAR File 7.1 Create Executable JAR File: todoapp.jar The javafxpackager utility program with the createjar command option is used to create an executable JAR file for the app.Create a directory called: deploy Create two sub-directories in the deploy directory: src and dest Place all the app’s class files in the src directory Navigate to the deploy directory run the following command from the DOS prompt:> javafxpackager -createjar -appclass TodoApp -srcdir src -outdir dest -outfile todoapp -v -classpath hsqldb.jar This creates the app’s executable JAR file. Verify that the file todoapp.jar is created in the dest directory. 7.2 Run the App Copy the created todoapp.jar file into the deploy (or any) directory. Note that the following are required before running the app:The hsqldb.jar file in the directory (or in classpath) The app’s database and the table are pre-created (see section Create App Database and Table)Run the app with one of the following ways: (a) From DOS command prompt: > java -jar todoapp.jar (b) Double-click the todoapp.jar file. 8. Download Java Source Code All the three versions of the source code can be downloaded from here: A JavaFX List Example. ...
jcg-logo

Java Design Patterns course launched on JCG Academy!

It has been a while since we have launched JCG Academy, a premium content, subscription based site offering a number of courses on the latest, cutting edge technologies, from NoSQL databases, like Redis and CouchDB, to mobile development with Android. Of course, Java related courses have a premier position there, and one of our most popular ones has just been completed. The Java Design Patterns course has officially launched as a standalone course. In this course you will delve into a vast number of Design Patterns and see how those are implemented and utilized in Java. You will understand the reasons why patterns are so important and learn when and how to apply each one of them.A design pattern is a general reusable solution to a commonly occurring problem within a given context in software design. A design pattern is not a finished design that can be transformed directly into source or machine code. It is a description or template for how to solve a problem that can be used in many different situations. Patterns are formalized best practices that the programmer can use to solve common problems when designing an application or system.   The course consists of 24 lessons, covering every Design Pattern under the sun. Here are the contents:Introduction to Design Patterns Adapter Design Pattern Facade Design Pattern Composite Design Pattern Bridge Design Pattern Singleton Design Pattern Observer Design Pattern Mediator Design Pattern Proxy Design Pattern Chain of Responsibility Design Pattern Flyweight Design Pattern Builder Design Pattern Factory Method Design Pattern Abstract Factory Design Pattern Prototype Design Pattern Memento Design Pattern Template Design Pattern State Design Pattern Strategy Design Pattern Command Design Pattern Interpreter Design Pattern Decorator Design Pattern Iterator Design Pattern Visitor Design PatternTo get you all on-board, we are offering the course for just $7.99 (instead of the original price $29.99) for a limited time only! Take the Course!   ...
software-development-2-logo

Why you should pay developers to learn

A true story We were having a meeting with a customer and he had just presented a project idea. He wanted us to give him a draft system architecture, supporting his project technical requirements. At one point, I was telling him that incremental development requires architecture evolution as well. When I said that finding the right architecture is also a learning process, he cut me off short with the following sentence:     Do you expect me to pay you to learn? To save the day, I told him I was referring to the business domain, we needed to fully understand in order to provide the right architecture. Do you want your project be developed by an unskilled team? Unless you hire a highly expensive consultant, chances are you need a software development team for more than a few months. If the project spans over a year or more, how would you feel about a team that never has time to level up? Software development is one of the most knowledge-driven industry, yet many expect developers to be readily equipped with everything it takes to solve any given problem. Languages keep on evolving. Relational databases keep on adding new features. There’s a plethora of NoSQL databases most have never ever worked with. Successful frameworks keep on releasing new versions. New techniques emerge (e.g. reactive programming or micro services), while others keep on getting more and more traction (e.g. functional programming). To master all these technologies and techniques you need to spend a considerable amount of time. When are developers supposed to level up? There are extremely passionate developers dedicating their spare time to reading books or technical articles or studying new technologies, but they are an exception to a rule. Most developers acquire all knowledge during their job and if you don’t invest in their skills they will never grow within your team. The right place and time to learn software is during your job. Unfortunately, not everybody in the software industry shares this vision of mine. Business owners don’t want to spend resources (time and money) on training developers. I really believe it’s a matter of perspective. If you don’t manage to get any direct or indirect revenue, you might be tempted to think you’re wasting money. But if you plan it properly, you can easily turn it into a very profitable investment. Learn for profit High quality software demands solid knowledge and expertize, but accumulating skills requires more than just reading. You need to become an active learner to maximize knowledge acquiring. I used to be a passive learner myself, only reading books and articles while constantly having the impression that I don’t actually make too much progress. When I started writing this blog, I realized I was now learning through teaching. When I became an active StackOverflow user, this feeling was reassured. When I started an open-source project, I finally realized that learning is only a side effect of hard working. All these examples are what active learning is all about. From the business perspective, it’s not difficult to foresee where the return of investment might come from:A more skilled development team can leverage more complex projects with a lower risk of failure. You can master a certain technology and start offering professional training and consultancy services You can write books and sell them through a self-publishing program. Ninja Squad’s AngularJS book (French) was a profitable investment after all.All in all, expertize always sells. Investing in developement skills can definitely payoff. Many developers enjoy a working environment where they can grow, so this move can actually be beneficial for employee retention as well. Starting on this journey is not as difficult as one might think, and I’m going to present some of my favorites active learning activities: Preparing a training material Let’s say you want to acquire a certain key technology skill in your company. Some developers should be partially allocated for studying and preparing a training material on this subject. A workshop is always a better choice than a simple presentation. When the training material is ready, you have accumulated both knowledge and a training base too. You can now start offering training or consultancy services on that particular technology. A company blog Every software company accumulates experience, yet few of them actually share it with the rest. A company technical blog can be a great marketing instrument. A high quality blog can prove your domain knowledge and expertize. You can build strategic partnerships with DZone or JavaCodeGeeks and therefore help promoting your business as well. Answering StackOverflow questions Contributing to StackOverflow is totally underrated. If you really want to become an expert into a certain domain, you should start answering question on that particular tag. When you answer a question you are reiterating your knowledge. Sometimes you only have a clue, so you start investigating that path, which not only provides you the right answer but it also allows you to strengthen your skills. It’s like constant rehearsing. After all, repetition is the mother of learning. Contributing to open source projects If you want to boost your design and coding skills, you should probably start contributing to open source projects. Browsing code can unveil certain patterns you’ve never previously applied. Most frameworks authors are incredibly craftsmen and their code review can teach you a lot about best programming practices. If your company makes heavy use of a certain open source technology, it’s a great idea to start contributing back. The best way to deal with an annoying framework issue is to actually fix it. Nobody knows a framework better than its own maintainers. Writing and selling books You can summarize all your experience in a book. Writing a book is very intense learning process as well. By the time you are done with it, you can really say you’ve come to master the subject. Amazon offers self publishing programs and selling books can become an alternative revenue source and an advertisement as well. Conclusion Embracing learning can be a competitive advantage for your company. Your products carry your company name, and a software product quality mirrors the development team professionalism. In the end, you are not only investing in individuals, you are investing in your own company as well.Reference: Why you should pay developers to learn from our JCG partner Vlad Mihalcea at the Vlad Mihalcea’s Blog blog....
Java Code Geeks and all content copyright © 2010-2015, Exelixis Media Ltd | Terms of Use | Privacy Policy | Contact
All trademarks and registered trademarks appearing on Java Code Geeks are the property of their respective owners.
Java is a trademark or registered trademark of Oracle Corporation in the United States and other countries.
Java Code Geeks is not connected to Oracle Corporation and is not sponsored by Oracle Corporation.
Do you want to know how to develop your skillset and become a ...
Java Rockstar?

Subscribe to our newsletter to start Rocking right now!

To get you started we give you two of our best selling eBooks for FREE!

Get ready to Rock!
You can download the complementary eBooks using the links below:
Close