Featured FREE Whitepapers

What's New Here?

play-framework-logo

Deploy Play Framework 2 apps to Openshift with Java AND Scala

A couple of weeks, Mark Atwood, Jorge Aliss, and me, Sebastián Scarano participated in Red Hat’s webinar LET’S PLAY! IN THE CLOUD: DEVELOPING JAVA WEB APPS ON OPENSHIFT In the webinar Mark gave a neat introduction to Openshift, Red Hat’s free Platform as a Service: Then we developed a basic contact manager web application, combining Java and Scala source code in the same Play 2 application, and deployed it on Openshift.   With this quickstart (https://github.com/opensas/play2-openshift-quickstart) you’ll be able to take any Play 2 application and deploy it on openshift. Just follow this instructions. And here (https://github.com/opensas/play2-contacts-demo) you will find the contact demo app. In the demo, in spite our internet connection conspiring against us, we managed to cover the following topics:Creating a new play 2 application Basic application structure Configuring your IDE to work with a Play application Routes Controllers Templates Models Persisting your data to an in-memory database with Ebean Adding Validations Working with Scala Templates Mixing Java and Scala source code in the same application Integrating twitter bootstrap Customizing your app cofiguration for running on Openshift Persisting your data to a file database when running on Openshift And finally, deploying your application on OpenshiftYou can also check this article in which we explain in detail how we took advantage of the new “do-it-yourself” application type on Openshift to achieve native support for Play Framework application on Openshift. So, if you want to start deploying your play apps on openshift right away, just sign up at openshift.com and enter PLAY!WEBINAR as promotional code, and you’ll get 3 gears, each with 1GB ram and 512 MB data space, for free. Have fun playing on the cloud! Reference: Deploying Play Framework 2 apps, with Java AND Scala, to Openshift from our JCG partner Sebastian Scarano at the Having fun with Play framework! blog....
opencv-logo

Binary websockets with Play 2.0 and Scala

In a recent article I showed how you can use webrtc, canvas and websockets together to create a face detection application whose frontend runs completely in the browser, without the need for plugins. In that article I used a Jetty based backend to handle the image analysis using OpenCV through the JavaCV wrapper. When I almost finished the article, I noticed that websockets is also supported from Play 2.0. I really like developping in Play and in Scala so as an experiment I rewrote the backend part from a Jetty/Java/JavaCV stack to a Play2.0/Scala/JavaCV stack. If you want to do this for yourself, make sure you start with the frontend code from here. Since the frontend code hasn’t changed except the location where the websockets are listening. Setting up the Play 2.0 environment I’m not going to talk too much about how to start a Play 2.0/Scala project. you can find the details in some of my other posts should you need more information. What we do need to do, is setup the dependencies for JavaCV so that they can be used from Play 2. I’ve manually added them to my local ivy repository, so that I can reference them from the sbt configuration like any other dependency. For my example I created the following directory layout for the JavaCV libraries: ./play-2.0-RC2/repository/cache/javacv ./play-2.0-RC2/repository/cache/javacv/javacpp ./play-2.0-RC2/repository/cache/javacv/javacpp/ivy-2.3.1.xml ./play-2.0-RC2/repository/cache/javacv/javacpp/ivydata-2.3.1.properties ./play-2.0-RC2/repository/cache/javacv/javacv ./play-2.0-RC2/repository/cache/javacv/javacv/ivy-2.3.1.xml ./play-2.0-RC2/repository/cache/javacv/javacv/ivydata-2.3.1.properties ./play-2.0-RC2/repository/cache/javacv/javacv-macosx-x86_64 ./play-2.0-RC2/repository/cache/javacv/javacv-macosx-x86_64/ivy-2.3.1.xml ./play-2.0-RC2/repository/cache/javacv/javacv-macosx-x86_64/ivydata-2.3.1.properties ./play-2.0-RC2/repository/local/javacv ./play-2.0-RC2/repository/local/javacv/javacpp ./play-2.0-RC2/repository/local/javacv/javacpp/2.3.1 ./play-2.0-RC2/repository/local/javacv/javacpp/2.3.1/ivys ./play-2.0-RC2/repository/local/javacv/javacpp/2.3.1/ivys/ivy.xml ./play-2.0-RC2/repository/local/javacv/javacpp/2.3.1/jars ./play-2.0-RC2/repository/local/javacv/javacpp/2.3.1/jars/javacpp.jar ./play-2.0-RC2/repository/local/javacv/javacv ./play-2.0-RC2/repository/local/javacv/javacv/2.3.1 ./play-2.0-RC2/repository/local/javacv/javacv/2.3.1/ivys ./play-2.0-RC2/repository/local/javacv/javacv/2.3.1/ivys/ivy.xml ./play-2.0-RC2/repository/local/javacv/javacv/2.3.1/jars ./play-2.0-RC2/repository/local/javacv/javacv/2.3.1/jars/javacv.jar ./play-2.0-RC2/repository/local/javacv/javacv-macosx-x86_64 ./play-2.0-RC2/repository/local/javacv/javacv-macosx-x86_64/2.3.1 ./play-2.0-RC2/repository/local/javacv/javacv-macosx-x86_64/2.3.1/ivys ./play-2.0-RC2/repository/local/javacv/javacv-macosx-x86_64/2.3.1/ivys/ivy.xml ./play-2.0-RC2/repository/local/javacv/javacv-macosx-x86_64/2.3.1/jars ./play-2.0-RC2/repository/local/javacv/javacv-macosx-x86_64/2.3.1/jars/javacv-macosx-x86_64.jar As you can see from this listing, I just added the three javacv supplied jars to my local repository. I also added a minimal ivy.xml so that they can be used from ivy and sbt. This minimal ivy.xml looks like this: <?xml version="1.0" encoding="UTF-8"?> <ivy-module version="2.0" xmlns:m="http://ant.apache.org/ivy/maven"> <info organisation="javacv" module="javacv-macosx-x86_64" revision="2.3.1" status="release"> </info><publications> <artifact type="jar"/> </publications> </ivy-module> With these files added to my repository I can setup the dependencies for the Play 2.0 project in the Build.scala file. import sbt._ import Keys._ import PlayProject._object ApplicationBuild extends Build {val appName = "PlayWebsocketJavaCV" val appVersion = "1.0-SNAPSHOT"val appDependencies = Seq( "javacv" % "javacv" % "2.3.1", "javacv" % "javacpp" % "2.3.1", "javacv" % "javacv-macosx-x86_64" % "2.3.1" )val main = PlayProject(appName, appVersion, appDependencies, mainLang = SCALA).settings( // Add your own project settings here ) } Now run “play update” and “play eclipsify” to update the dependencies and your Eclipse configuation (if you’re using Eclipse that is). Configure websockets in Play Using websockets in Play 2.0 is very easy. The first thing you need to do is add the URL to your routes configuration in the conf directory. GET /wsrequest controllers.Application.wsrequest And, of course, you need to implement the action this route points to: /** * Simple websocket listener configured in play 2. This uses a synchronous model, where * the same channel is used to send the response. For this usecase this is useful, if * we want async processing we could have used Akka actors together with play 2.0 async * support. */ def wsrequest = WebSocket.using[Array[Byte]] { request =>// Create the outbound value that is called for each val out = Enumerator.imperative[Array[Byte]]();val in = Iteratee.foreach[Array[Byte]](content => { out.push(FaceDetect.detect(content)); })// tie the in and out values to each other (in, out) } In this code we configure an input channel (in), and an output channel (out) and connect them to the socket. Whenever the HTML5 client sends a request over the websocket our “in” method is called, and when we want to send something to the client we can use the “out” channel. The “in” channel needs to be defined as an Iteratee (more info see these Play docs). What this does is, that for each input message we receive we run the specifici method. In this case we run the FaceDetect.detect operation (more on this later) and the result from this operation is pushed back to the client using the “out” channel. This “out” channel itself is defined as an Enumerator (see these play docs). We can attach different listeners if we want to this enumerator, but in this case we don’t do anything with the message, just pass it along to the client. Using JavaCV from scala The last step is the code of the FaceDetect.detect function. The java version, see earlier mentioned article, is very easily converted to a scala one. package javacvimport com.googlecode.javacv.cpp.opencv_core._ import com.googlecode.javacv.cpp.opencv_imgproc._ import com.googlecode.javacv.cpp.opencv_highgui._ import com.googlecode.javacv.cpp.opencv_objdetect._ import com.googlecode.javacpp.BytePointer import java.nio.ByteBuffer import javax.imageio.ImageIO import java.io.ByteArrayOutputStream import scala.tools.nsc.io.VirtualFileobject FaceDetect {var CASCADE_FILE =PATH_TO_CASCADE_FILE; var minsize = 20; var group = 0; var scale = 1.1;def detect(imageData:Array[Byte]) : Array[Byte] = {// we need to wrap the input array, since BytePointer doesn't accept // a bytearray as input. It accepts a byte varargs, but Array[Byte] // doesn't convert automatically var wrappedData = ByteBuffer.wrap(imageData); var originalImage = cvDecodeImage(cvMat(1, imageData.length,CV_8UC1, new BytePointer(wrappedData)));// convert to grayscale for easy detection var grayImage = IplImage.create(originalImage.width(), originalImage.height(), IPL_DEPTH_8U, 1); cvCvtColor(originalImage, grayImage, CV_BGR2GRAY);// storage is needed to store information during detection var storage = CvMemStorage.create();// load and run the cascade var cascade = new CvHaarClassifierCascade(cvLoad(CASCADE_FILE)); var faces = cvHaarDetectObjects(grayImage, cascade, storage, scale, group, minsize);// draw a rectangle for the detected faces for (i <- 0 until faces.total) { var r = new CvRect(cvGetSeqElem(faces, i)); cvRectangle(originalImage, cvPoint(r.x, r.y), cvPoint(r.x + r.width(), r.y + r.height), CvScalar.YELLOW, 1, CV_AA, 0); }// convert to bytearray and return var bout = new ByteArrayOutputStream(); var imgb = originalImage.getBufferedImage(); ImageIO.write(imgb, "png", bout);bout.toByteArray() } } The only issue I ran into was with the BytePointer constructor. One of the signatures accepts a varargs of the type byte. In java this allows me to just supply this constructor with a byte[], in Scala however this doesn’t work. Luckily though, a BytePointer can also be created using a ByteBuffer. For the rest this is a one-to-one conversion of Java to Scala. Running the code And that’s almost it. By default play listens on port 9000, in the Jetty based example we had the server running on 9999 and listening to the root context. To work with our Play2/Scala based server we just need to point the browser to the correct websocket server url. ws = new WebSocket("ws://127.0.0.1:9000/wsrequest"); And now, when we run it, we use Play 2 as our server and run the JavaCV code using scal. And more importantly it still works: Reference: Binary websockets with Play 2.0 and Scala (and a bit op JavaCV/OpenCV) from our JCG partner Jos Dirksen at the Smart Java blog....
hamcrest-logo

JUnit and Hamcrest: Improving On assertEquals

In my blog post Are Static Imports Becoming Increasingly Accepted in Java?, I discussed the increasing use of static imports in Java to make code more fluent in certain contexts. Unit testing in Java has been particularly affected by the static import and in this blog post I provide one quick example of using static imports to make more fluent unit tests that use JUnit and Hamcrest. The next code listing is a simple IntegerArithmetic class that has one method that needs to be unit tested. IntegerArithmetic.java package dustin.examples;/** * Simple class supporting integer arithmetic. * * @author Dustin */ public class IntegerArithmetic { /** * Provide the product of the provided integers. * * @param integers Integers to be multiplied together for a product. * @return Product of the provided integers. * @throws ArithmeticException Thrown in my product is too small or too large * to be properly represented by a Java integer. */ public int multipleIntegers(final int ... integers) { int returnInt = 1; for (final int integer : integers) { returnInt *= integer; } return returnInt; } }A common approach for testing one aspect of the above method is shown next. /** * Test of multipleIntegers method, of class IntegerArithmetic, using standard * JUnit assertEquals. */ @Test public void testMultipleIntegersWithDefaultJUnitAssertEquals() { final int[] integers = {2, 3, 4 , 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}; final int expectedResult = 2 * 3 * 4 * 5 * 6 * 7 * 8 * 9 * 10 * 11 * 12 *13 * 14 * 15; final int result = this.instance.multipleIntegers(integers); assertEquals(expectedResult, result); }In the fairly typical unit test example shown above, JUnit’s assertEquals is called in a fluent fashion because of the static import of org.junit.Assert.* (not shown). However, recent versions of JUnit (JUnit 4.4+) have begun including Hamcrest core matchers and this allows for an even more fluent test as depicted in the next code snippet. /** * Test of multipleIntegers method, of class IntegerArithmetic, using core * Hamcrest matchers included with JUnit 4.x. */ @Test public void testMultipleIntegersWithJUnitHamcrestIs() { final int[] integers = {2, 3, 4 , 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}; final int expectedResult = 2 * 3 * 4 * 5 * 6 * 7 * 8 * 9 * 10 * 11 * 12 *13 * 14 * 15; final int result = this.instance.multipleIntegers(integers); assertThat(result, is(expectedResult)); }In this example, JUnit’s assertThat (also available as part of the static import of org.junit.Assert.* since JUnit 4.4) is used in conjunction with the included Hamcrest core matcher is(). It’s certainly a matter of taste, but I prefer this second approach as more readable to me. Asserting that something (the result) is something else (the expected) seems more readable and more fluent than the older approach. It can sometimes be tricky to remember whether to list the expected or actual result first when using assertEquals and the combination of assertThat and is() makes for a little less work when I write and read tests. Even a little less work, especially when multiplied by numerous tests, is welcome. Reference: Improving On assertEquals with JUnit and Hamcrest from our JCG partner Dustin Marx at the Inspired by Actual Events blog....
javafx-logo

JavaFX 2 vs. HTML5 for RIA

These days, we are starting a new project for realizing a Rich Internet Application (RIA). One of the first questions is: Which technologies and frameworks shall we use? The backend will be Java or another modern JVM language, as we are mainly experienced Java developer. In most use cases, we also prefer web frameworks, which allow to code mostly in Java, as many of us just have basic knowledge regarding HTML and JavaScript. A decision has to be made for the upcoming project: Shall we use HTML5 or JavaFX 2 for realizing the web client? If you ask Google for “javafx or html5”, you do not find much information. In the majority of cases, you end up with a presentation hold at several IT conferences in 2011: “Moving to the Client: JavaFX and HTML5 Presentation”. Here is the Slideshare link (from JavaOne 2011): http://www.slideshare.net/steveonjava/moving-to-the-client-javafx-and-html5. Because this presentation does not help much, we took a look at pros and cons, which are listed below in this blog post. But let’s start from the beginning… What is a Rich Internet Application (RIA)? There is no real definition for RIA. Therefore, here is my definition for this blog post: “A Rich Internet Application provides a modern looking web application with animations, effects and multimedia features. The web application is hardly recognizable as web application. There is no classic HTML user interface with forms, drop down boxes or tables. Typical features of web browsers such as bookmarking or forwards / backwards navigation are usually missing / not required. Sometimes (i.e. if you use a web framework instead of just HTML5), a plugin must be installed (e.g. Java Runtime Environment or Adobe Flash Player). Pokerstars (www.pokerstars.com) is a very good example for a RIA.” Alternatives Several alternatives are available in the JVM environment for realizing a RIA:Plain HTML5: Good solution, but you do not code in Java or another JVM language. Adobe Flash / Flex: Dead! Even Adobe moves to HTML5. Microsoft Silverlight: Dead! Even Microsoft Windows 8 moves to HTML5. (Of course, Silverlight is no real JVM solution, but you can make it work together with JVM backend. For the sake of completeness, I added it to this list.) JavaFX: Java-based solution (replacement for Swing in the future). Other JVM web frameworks besides JavaFX (JSF, GWT*, Wicket, Tapestry, Grails, Lift, “You-Name-It”): Not built for realizing RIAs. Yes, you can realize a RIA with these frameworks. Though, development is ugly, and the RIA will be ugly, too. So why would you do this? (Please remember my above definition of a RIA before you begin complaining in the comments!)* GWT also has nice (experimental) HTML5 support for some features already: http://www.google.com/events/io/2011/sessions/gwt-html5-a-web-developers-dream.html => If Google continues adding support for HTML5 to GWT, this may be a good alternative in the next years, too – you develop only in Java, and you do NOT need a browser plugin because GWT generates plain HTML and JavaScript. However, there are also rumors that GWT is dying due to Google’s new language Dart. Google did not comment this yet, or release a roadmap for GWT. So, the question is when to use JavaFX 2 instead of HTML5 for realizing a RIA (from the view of a Java developer)? If you do not know much about HTML5 or JavaFX, you should look at Wikipedia or google for other articles. What is HTML5? => http://en.wikipedia.org/wiki/Html5 Important: HTML5 is HTML + CSS + JavaScript! It offers several next generation features for modern web development, such as Offline Storage or Application Cache. What is JavaFX? => http://en.wikipedia.org/wiki/Javafx Reminder: We are talking about JavaFX 2.0. The main difference to earlier versions is that JavaFX now offers a Java API instead of a new programming language (JavaFX Script). Thus, it is easy to learn for a Java developer. Why HTML 5 / JavaScript? ProsW3C standard It’s the future – no question! No plugin is required, can be used in every (supported) web browser Already many widgets and features availableConsDevelopment with HTML / JavaScript instead of Java => Main disadvantage for a Java developer! Spec not final yet (according to the roadmap not before 2014!) Not supported by all browsers (yet) Cross-browser development is necessary (JavaScript frameworks such as jQuery or Dojo solve this problem, but increase efforts nevertheless)Probably, there are many other pros and cons for HTML5. Though, the named ones should be sufficient for deciding when to use HTML5 or JavaFX. Why JavaFX 2? ProsOffers a Java API => Leverage your Java skills and use existing JVM features and libraries Offers DSLs for further JVM languages, e.g. Groovy (GroovyFX) and Scala (ScalaFX). Read this article to learn how to benefit by using modern JVM languages instead of Java: “JavaFX 2.0 and Scala, Like Milk and Cookies” => http://www.javacodegeeks.com/2012/02/javafx-20-and-scala-like-milk-and.html optional: “layouting” language FXML to split UI definition from behaviour => choose your favorite between programming (with Java) and layouting (with FXML) Same development environment for backend and web client (including debugging, refactoring, etc.) No cross-browser problems CSS support (as in HTML) HTML and / or JavaScript can be integrated in a JavaFX application Swing and JavaFX can be used in same application, so existing Swing applications can be extended JavaFX 2 provides a unified architecture for writing an application once and then deploying it to various contexts (standalone application, embedded in a web browser or run via Java Web Start). Additional contexts will be added in the future (e.g. running the same application on a mobile device).ConsJava Runtime Environment is required on client Only parts of JavaFX are open source. The Oracle JavaFX runtime and SDK will continue to be released under the Java Binary Code License JavaFX for Mac only available as Developer Preview (GA planned for the mid of 2012) => see JavaFX roadmap JavaFX for Linux not available yet (Developer Preview planned for Q3 of 2012) No information about future of JavaFX Mobile yet (at least I did not find anything, if someone has a link, please add a comment!) Offers less widgets and other features than HTML5 Though JavaFX is the (future) replacement for Swing, development is different due to several new concepts. Of course, this is the consequence of adding RIA features such as animations => Thus, this is no real disadvantage, and its still easier for a Java developer to learn some new concepts than learning HTML and JavaScriptConclusion HTML5 and JavaFX 2 are both awesome for realizing RIAs including media, charts, animation, etc. In the end, both have a different target audience:Public web applications should be realized with HTML5, because requiring a browser plugin is a no-go in most use cases. Therefore, even for Java developer there is no alternative to HTML5. Within an enterprise, it may be acceptable to require a plugin. Probably, Java is already installed on most machines anyway. If all needed widgets and other features are available, JavaFX is the better choice for enterprise applications because a Java developer can realize RIAs much easier by developing in its well-known JVM environment.Have fun realizing your RIA with HTML5 or JavaFX 2. By the way: We will probably choose JavaFX for our internal project because the required Java plugin is no show-stopper and most colleagues are Java developer. Reference: When to use JavaFX 2 instead of HTML5 for a Rich Internet Application (RIA)? from our JCG partner Kai Wahner at the Blog about Java EE / SOA / Cloud Computing blog....
software-development-2-logo

Tips For Developing Multilingual Software Applications

Why is software localization important? The very nature of software applications means they can usually be accessed, bought and downloaded regardless of geographic location. The World Wide Web provides potential access to a truly global market but a monolingual application is one with limited appeal. To a certain extent, English remains the lingua franca of the business and online world but the fact remains that the majority of the global population speaks no English at all. Of those that do, many speak it as a second language and multilingual users prefer to use applications in their own native language. Imagine a French student who speaks passable English. If your English language application has a specific appeal and no French language equivalent exists, he might well decide to use your application. If there a rival application of similar function and quality that is also available in French however, he is far more likely to go for that. Localization and the simship model Localization (often abbreviated in computing circles to L10n, with the 10 representing the number of letters between the “L” and the “n”) is simply the process of adapting a piece of software for use in another locale. Essentially, this means releasing a number of separate products with each tailored for use within its own target market. These individual localized apps certainly don’t have to be designed independently however. The source code largely remains the same but linguistic translation will often be required and certain cultural and legal issues such as copyright and taste may also have to be addressed. Building flexibility into the design should allow you to adapt the app subsequently without too many problems. At the time of initial release you might only want a single version, with the option to produce localized versions when circumstances and market research dictates. There are various issues that can be partially catered for during the design and development stage. Some written languages or scripts tend to take more space on the screen for example and areas with fixed dimensions such as dialog boxes can be sized to allow a subsequent expansion of text. Alternatively, you may wish to release several versions simultaneously. The simship (simultaneous shipment) model is common within the gaming industry and, given that successful apps can tend to go viral, spreading by virtual “word of mouth,” it can be a tremendous asset to have localized versions ready to go at the same time. Internationalized apps Internationalization (also known as i18n for the same reason localization is L10n) takes things a step further, with a single application able to cater to users in different languages. The most common method is to have a language selection option the first time a user accesses the application. This then serves as a portal to the relevant user interface and content. This is not the only solution. It is possible to have multiple languages present on the same screen for example but this tends to be a messier and more confusing way of doing things. Issues of translation Linguistic translation is not the only issue to think about but it is perhaps the most important. Good quality translation is integral to the quality of a localized, multilingual or internationalized app and the services of native speaking translators will usually be required. Automatic translation programs can be great tools under certain circumstances but they are prone to contextual mistakes and should never be solely relied upon. The user interface (UI), input and display are all obvious areas for translation but other aspects such as product documentation and online help files will also need to be addressed. What about graphics? Some images work more or less universally while others may have different connotations in different areas. An envelope is generally recognized as a symbol for mail while a thumbs up sign can mean “okay” in the western world but is more likely to mean ‘man’ or ‘male’ in Japan and is an obscene gesture in Thailand and Iran. Additionally, some images that may be perfectly acceptable in one culture can cause offence in another. In addition to translating the text and making sure any images are culturally relevant and sensitive, you should also ensure that the formats for currencies, units of measurement, time and dates are all correct for the target market. In the US, for example, the date is expressed in the Middle-endian fashion (month/day/year) but most of the rest of the world uses the Little-endian format (day/month/year). There is a lot to consider when it comes to developing localized and multilingual software applications. Given the potential benefits in terms of opening up new markets and sales, however, it is a process that is more than worth the effort. This was a guest post from Christian Arno. Christian is the founder of Lingo24, a leading translation service provider across Europe, Asia and the Americas. Launched in 2001, Lingo24 has worked its way to becoming the web’s favorite translation company, working with more than four thousand translators and clients in over sixty countries.Follow Christian (@l24ca) and Lingo24 (@Lingo24) on Twitter. Related articlesThe Multilingual Web (blogs.adobe.com) Dynamic Language Delivery for Adobe’s Mobile Applications (blogs.adobe.com) Niklas Laxström, language engineer and Wikimedian (wikimedia.org)Reference: Tips For Developing Multilingual Software Applications from our JCG partner Rob Diana at the Regular Geek blog....
software-development-2-logo

Software architect mistakes

I think that to get up in the morning and brew a good cup of coffee is one of the best way to start the day. You know, the heady fragrance that emanates from the machine-pot, it?s delicious. When it?s ready, pour the coffee into a cup, add some sugar, and finally you got it end of the coffee making process. Have you ever thought to design a coffee making process with some diagrams, or doing the same with other banal activities such as taking a shower? Of course not. For other cases less trivial than these, including software project development, a minimal-design work can be quite useful and somewhat needed. Often questions arise; is an architecture design worth the time and effort invested in it? Well, you may answer this question first: Are there risks in the project that could be minimized by an early design activity? The more ambitious and challenging the project is, the higher the number of risks, and the more difficult it is to complete successfully. How to identifying risks. The easiest place to start is with requirements, in whatever form they take, and to look for things that seem difficult to achieve. Gathering requirements is fundamental for deciding what to do and how. However, sometimes problems arise at this starting point that lead to the ruination of the project. Some assumptions may underestimate this key phase and shake the architect role to its foundations: 1. It?s someone else? responsibility to do requirements. Domains drive the architecture choices, not vice-versa. Requirements can create architecture problems. At the very least, you need to assist the business analysts. 2. I learn the domain as I write the code; incrementally. While prototyping pieces of software is a way for mitigating engineering risks and figuring out the hardest problems, writing code could be a waste of time for analyzing a domain. Rather, it?s very cost-effective to modelling it in advance. 3. The requirements are already fully understood by the stakeholders. Clear communication is critical between people and the role of a software architect can be a very difficult one when others don?t understand what you do and why. 4. Domains are irrelevant to architecture choice. Developers may copy an architecture from a past project. Maybe just following the company standard, but ignoring the motivations behind previous choices. They are more likely to be unaware of the qualities required in the current project. 5. I already know the requirements. At least the documentation should be in your mind, but designers should use models to amplifying their reasoning abilities and unfold not clearly visible aspects that affect their own risks. Reference: Software architect mistakes from our JCG partner Giancarlo Frison at the Making Things Simple Through The Complex blog....
apache-shiro-logo

Secure Encryption in Java

Last time I wrote about cryptography, I outlined Apache Shiro crypto API and shown how to use its two symmetric ciphers. I also wrote that “You do not need more to encrypt and decrypt sensitive data in your applications.” I learned more about cryptography and found out that you need to know more. What I wrote is true to some extend, but unless you are careful your sensitive data may not be secure against all attackers. Out of the box Shiro provides Blowfish-CBC and AES-CBC encryption methods and I recommended to use them. Both have been designed to protect against passive eavesdropping attacker and are good at it. Unfortunately, real attackers are more sophisticated and may break the system based on them. Notice the “may”. The attacker can succeed only if attacked system cooperates with him at least little bit. If you want to use these ciphers, you have to know how to write the system securely. Of course, the other option is to use stronger cipher and avoid the problem completely. Few needed theoretical terms and concepts are explained in the first chapter. Second chapter shows how to encrypt data in a more secure way. Then we describe how Blowfish-CBC and AES-CBC work and show two possible attacks on them. Finally, the end of the post contains references to other resources Theory We start with a few theoretical concepts. If you do not want to read it, go directly to the chapter with the solution. First important thing to describe is the difference between a passive and an active attacker. Then we explain what are block ciphers and what is an authenticated encryption. Last two subchapters list selected vulnerable and selected secure ciphers. Active vs Passive Attacker Eavesdropping only attacker is mostly passive. He is able to read encrypted communication, but is unable to modify it or send new ciphertexts to communicating applications. He is not able to influence the communication, he only listens to it. His passivity has only one exception: the attacker is able to give unencrypted information to one of communicating parties and obtain ciphertext with that exact information. Real-world attackers are often more active. They compose their own messages and send them to communicating application. The application then assumes that those messages are encrypted, so it tries to decrypt them. The attacker observes its reaction (returned error code, time needed to answer and so on), and learn more about the cipher. If he is lucky, he may use obtained knowledge to break the cipher or to plant false information. Block Ciphers Block ciphers are able to encrypt only short messages. For example, AES can encrypt only 16 bytes long messages and Blowfish is able to encrypt only 8 bytes long messages. Longer messages are split into blocks. Each block is combined with previously encrypted blocks and passed to the block cipher. Block combining is called an operation mode and there are multiple secure ways how to do it. Two active attacks discussed in this post are attacks on CBC operation mode. Block ciphers themselves are secure. Authenticated Encryption Authenticated encryption rejects any modified ciphertext as invalid. It is not possible to take encrypted data, modify them and end up with valid ciphertext. This property is also called a ciphertext integrity. The cipher checks integrity first and rejects all modified messages the same way. As the attacker can not pass through the integrity check, he gains nothing from sending new messages to the application. Authentication and ciphertext integrity are usually, but not always, provided by the operation mode. Vulnerable Ciphers Any cipher that does not provide ciphertext integrity or authenticated encryption is probably vulnerable to some active attack. It does not matter which encryption library is used. Encryption algorithms are defined in standards and amount to the same thing regardless of the used library. Otherwise said, if it is possible to create valid ciphertext without knowing the secret key, then it is likely that some active attack exists, even if it is not know yet. This post describes two attacks CBC operation mode. Once you understand both these attacks and differences between passive and active attacker, you should be able to come up with similar attacks on CFB, CTR, OFB or other non-authenticated cipher modes. Secure Ciphers Authenticated encryptions are secure against active attackers. Most common operation modes that provide also authentication are:GCM EAX CCMReplace CBC with one of these modes (e.g. AES-EAX) and you have a cipher secure against an active attacker. Of course, secure against an active attacker does not mean that the cipher has no other real-world limitation. For example, most ciphers are safe only if the user changes the key after too much data have been encrypted. If you are serious about data encryption, you should study and know those limitations. Authenticated Encryption with Shiro This chapter shows how to use an authenticated encryption in Java. For those who skipped the theory, authenticated encryption protects against data tampering. Nobody without the secret key will be able to modify an encrypted message and an active attack on such cipher is impossible. Apache Shiro does not implement its own encryption algorithms. It delegates all work to Java Cryptography Extension (JCE) which is available in each Java runtime. Shiro ‘only’ provides easy to use API and secure defaults. Therefore, we have to do two things:install authenticated operation modes into Java Cryptography Extension, integrate Shiro with new authenticated operation modes.Install Authenticated Operation Modes Java Cryptography Extension is an extensible API. All classes and algorithms are created by providers and new provider can be installed into the system at any time. The provider can be either:installed into java runtime and be available to all java applications, distributed and initialized together with the application.We will show how to add Bouncy Castle into the project. Bouncy Castle is a provider distributed under the MIT license and contains both EAX and GCM operation modes. Bouncy Castle distributes multiple jar files, each optimized for different java version. As our demo project uses Java 6, we have to use bcprov-jdk16 library. Add maven dependency into pom.xml: <dependency> <groupId>org.bouncycastle</groupId> <artifactId>bcprov-jdk16</artifactId> <version>1.46</version> </dependency>Once the library is present, you have to install its provider into java security system. Run following method at the application start-up: private BouncyCastleProvider installBouncyCastle() { BouncyCastleProvider provider = new BouncyCastleProvider(); Security.addProvider(provider); return provider; }Bouncy Castle is now installed and both authenticated operation modes are available. Integrate with Shiro Shiro cryptography package is basically an easy to use facade over JCE. It configures JCE objects to use secure defaults and adds thread safety to it. Extend DefaultBlockCipherService class to take advantage of these features. Most of configuration is done by that class, but we still have to specify three things:block cipher name and parameters, operation mode, padding.Block cipher name is specified in constructor parameter. We will use AES, because it requires no additional configuration. Neither GCM nor CCM require padding, so we have to specify the padding NONE. New cipher service: class GCMCipherService extends DefaultBlockCipherService {private static final String ALGORITHM_NAME = "AES";public GCMCipherService() { super(ALGORITHM_NAME); setMode(OperationMode.GCM); setPaddingScheme(PaddingScheme.NONE); }}That is it. You may use the new authenticating cipher as any other Shiro cipher service. Test Case We created a simple test case to demonstrate that the integrity check works. It encrypts a message and changes third byte of its ciphertext. If the cipher provides an authentication, then an attempt to decrypt modified ciphertext results in runtime exception: @Test public void testGCMAuthentication() { String message = "secret message";GCMCipherService gcmCipher = new GCMCipherService(); assertIngetrityCheck(message, gcmCipher); }private void assertIngetrityCheck(String message, DefaultBlockCipherService cipher) { byte[] key = cipher.generateNewKey().getEncoded(); byte[] messageBytes = CodecSupport.toBytes(message); ByteSource encrypt = cipher.encrypt(messageBytes, key);// change the ciphertext encrypt.getBytes()[3] = 0;try { // it should be impossible to decrypt changed ciphertext cipher.decrypt(encrypt.getBytes(), key).getBytes(); } catch (Exception ex) { return; } fail("It should not be possible to decrypt changed ciphertext."); }Note on Java 7 According to documentation, Java 7 supports two authenticated operation modes: CCM and GCM. Theoretically, you should not need a third party cryptography provider. Unfortunately, Oracle could not provide a full implementation of these modes in first JDK 7 release. They would like to add it in an update release, so the situation may change in the future. Oracle bug database contains two related bugs. Java 1.7.0_01 still does not have them. Cipher Block Chaining (CBC) The last thing we needed before we can describe promised attacks is cipher block chaining (CBC) operation mode. This operation mode is sufficiently secure against passive attacker, reasonably fast and easy to implement. Unfortunately, it also is vulnerable to active attacks. Basics CBC is used to encrypt a long message with block cipher. Block ciphers are able to encrypt only short blocks of data, so it starts by splitting the message into short blocks. First and last blocks are special cases. We will explain what to do with them in following subchapters. For now, assume that the message beginning is already encrypted and its i-th block mi corresponds to ciphertext ci. Encrypt the next message block in two steps:xor the block with ciphertext of the previous block (e.g. mi?ci-1), encrypt the result with a block cipher (e.g. Blowfish(key, mi?ci-1)).Example: suppose that the secret message has three blocks and we are trying to encrypt it with Blowfish-CBC. The first block is already encrypted and its ciphertext is 1, 2, 3, 4, 5, 6, 7, 8. The second block is a byte array 1, 0, 1, 0, 1, 0, 1, 0. Step 1: xor the first block ciphertext with the second block: 1, 2, 3, 4, 5, 6, 7, 8 ? 1, 0, 1, 0, 1, 0, 1, 0 = 0, 2, 2, 4, 4, 6, 6, 8Step 2: encrypt the result with blowfish algorithm: Blowfish(secret_key, {0, 2, 2, 4, 4, 6, 6, 8})First Block – Initialization Vector First block has no previous block to be combined with. Therefore, we will generate a block of random data called initialization vector. The initialization vector is used as a very first block of data. It is xor-ed with the first message block and the result is encrypted with a block cipher. Initialization vector is send unencrypted as a first block of the ciphertext. The recipient would be unable to decrypt the ciphertext without it and there is no reason to keep it secret. Example: suppose that the secret message has three blocks and we are trying to encrypt it with Blowfish-CBC. The first block is a byte array 1, 1, 1, 1, 1, 1, 1, 1. Step 1: generate random initialization vector: 1, 8, 2, 7, 3, 6, 4, 5Step 2: xor the first block with the initialization vector: 1, 8, 2, 7, 3, 6, 4, 5 ? 1, 1, 1, 1, 1, 1, 1, 1 = 0, 9, 3, 6, 2, 7, 5, 4Step 3: encrypt the result with blowfish algorithm: Blowfish(secret_key, {0, 9, 3, 6, 2, 7, 5, 4})Step 4: combine initialization vector and ciphertext. If the result of Blowfish function in previous step is 1, 2, 3, 4, 5, 6, 7, 8, then the ciphertext is: 1, 8, 2, 7, 3, 6, 4, 5, 1, 2, 3, 4, 5, 6, 7, 8Last Block – Padding Block ciphers are able to encrypt messages of fixed length and last block is often shorter than that. As the cipher is unable to encrypt it, we need a way to add additional bytes to the end of the message. Shiro uses PKCS#5 padding by default. Each its byte is equal to the length of the padding:If the last block is too short, count how many bytes are missing and fill missing bytes with that number. If the last block has the right size, treat the message as if it would be missing whole block. Add a new padding block to it. Each its byte will be equal to the block size.Example 1: suppose that the secret message has three blocks and we are trying to encrypt it with Blowfish-CBC. The last block is byte array 1, 1, 1, 1. Padded block: 1, 1, 1, 1, 4, 4, 4, 4Example 2: suppose that the secret message has three blocks and we are trying to encrypt it with Blowfish-CBC. The last block is byte array 8, 7, 6, 5, 4, 3, 2, 1. Last block and padding: 8, 7, 6, 5, 4, 3, 2, 1, 8, 8, 8, 8, 8, 8, 8, 8Attacks Finally, we are ready to show two different attacks on CBC based ciphers and prove that the problem is real. Our sample project contains tests cases for both attacks on both AES-CBC and Blowfish-CBC ciphers. First subchapter shows how to change the beginning of encrypted text to any message of our choice. Second subchapter explains how to decrypt the ciphertext. Data Tampering Data tampering attack is possible only if the attacker already knows the content of encrypted message. Such attacker can change first message block to whatever he wishes to. In particular, it is possible to:change first 16 bytes of AES-CBC encrypted message, change first 8 bytes of Blowfish-CBC encrypted message.Potential Danger Whether this type of attack is dangerous depends a lot on circumstances. If you use the cipher to send password through network, then data tampering is not so dangerous. At worst, a legitimate user will get login denied. Similarly, if your encrypted data are stored on some read-only storage, then you do not have to worry about data tampering. However, if you are sending bank order through the network, data tampering is a real threat. If someone changes the message Pay Mark 100$ into Pay Tom 9999$, Tom will get 9999$ he should not get. The Attack Encrypted message has three parts:random initial vector, first block of ciphertext, the rest of the message.The recipient decrypts the first block of ciphertext with the block cipher. This gives him message block?initial vector. To get the message, he has to xor this value with the initial vector: message block ? initial vector ? initial vector = message block The initial vector is transferred together with the message and an active attacker can change it. If the attacker replaces the original initial vector with another iv, then the recipient will decrypt another message: message block ? initial vector ? another iv = another message Rearrange the previous equation and you get: another iv = message block ? initial vector ? another message If the attacker knows both initial vector and content of the encrypted message, then he can modify the message to anything he wants. All he has to do is to xor the original initial vector with both known message content and desired message. Whoever decrypts the modified ciphertext will obtain a modified message instead of the original one. Test Case We created a simple test case that demonstrate this attack on a message encrypted with AES-CBC. Imagine that an attacker captured an encrypted email and somehow knows what is in it: //original message private static final String EMAIL = "Hi,\n" + "send Martin all requested money please.\n\n" + "With Regards, \n" + "Accounting\n";The attacker can change only first 16 bytes of the message, so he decides to redirect the money to Andrea: //changed message private static final String MODIFICATION = "Hi,\n" + "give Andrea all requested money please.\n\n" + "With Regards, \n" + "Accounting\n";Following test case encrypts the message and modifies the ciphertext. Modified ciphertext is decrypted and compared to the expected message: @Test public void testModifiedMessage_AES() { //create cipher and the secret key StringCipherService cipher = new StringCipherService(new AesCipherService()); byte[] key = cipher.generateNewKey();//encrypt the message byte[] ciphertext = cipher.encrypt(EMAIL, key);//attack: modify the encrypted message for (int i = 0; i < 16; i++) { ciphertext[i] = (byte)(ciphertext[i] ^ MODIFICATION.getBytes()[i] ^ EMAIL.getBytes()[i]); }//decrypt and verify String result = cipher.decrypt(ciphertext, key); assertEquals(MODIFICATION, result); } Of course, similar attack can be done on Blowfish-CBC. We can change only first 8 bytes this time: @Test public void testModifiedMessage_Blowfish() { String email = "Pay 100 dollars to them, but nothing more. Accounting\n"; StringCipherService cipher = new StringCipherService(new BlowfishCipherService()); byte[] key = cipher.generateNewKey(); byte[] ciphertext = cipher.encrypt(email, key);String modified = "Pay 900 dollars to them, but nothing more. Accounting\n"; for (int i = 0; i < 8; i++) { ciphertext[i] = (byte)(ciphertext[i] ^ modified.getBytes()[i] ^ email.getBytes()[i]); } String result = cipher.decrypt(ciphertext, key); assertEquals(modified, result); } Decrypt the Cipher The second attack allows an attacker to decrypt the secret message. The attack is possible only if the application that decrypts secret messages cooperates with the attacker. Padding Oracle The attacker creates a lot of fake ciphertexts and sends them to the recipient. As he tries to decrypt those messages, one of these things will happen:the ciphertext decrypts to meaningless garbage, modified message will not be valid ciphertext at all.If the application behaves the same way in both cases, then everything is ok. If it behaves differently, then the attacker is able to decrypt the ciphertext. There is only one way how the CBC based ciphertext can be incorrect – if the padding is wrong. For example, if ciphertext contains an encrypted password, the vulnerable server may respond with “login denied” in case of wrong decrypted password and with runtime exception in case of invalid ciphertext. If this is the case, then the attacker can recover the password. General Idea Each fake message has two parts: a fake initial vector and one message block. Both are sent to the server. If it answers “padding right”, then we know that: message ? original iv ? fake iv = valid paddingThe only unknown variable in the above equation is the message. The original iv is previous ciphertext block, fake iv was created by us and the valid padding is one of 1 or 2, 2 or 3, 3, 3 or ... or 8, 8, ..., 8 and so on. Therefore, we can calculate the block content as: message = valid padding ? original iv ? fake ivAlgorithm Start by recovering the last block byte. Each fake initial vectors starts with a lot of 0 and ends with a different last byte. This way, we can be almost sure that the server answers “padding right” only on a message that ends with 1. Use the previous chapter equation to calculate the last block byte. Getting the second last byte of the message is very similar. The only difference is that we have to craft a ciphertext that decrypts into the second shortest padding 2, 2. The last byte of the message is already known, so enforcing 2 as the last value is easy. The beginning of the initial vector is unimportant and set that to 0. Then we try all possible values for the second last byte of the initial vector. Once the server answers “padding right”, we can get the second last message byte from the same formula as before: original iv ? fake iv ? 2. We calculate third last message byte out of fake message with padding 3, 3, 3; fourth out of message with padding 4, 4, 4, 4; and so on until the whole block is decrypted. Test Case The vulnerable server is simulated with a PaddingOraculum class. Each instance of this class generates a random secret key and keeps it private. It exposes only two public methods:byte[] encrypt(String message) – encrypts a string with secret key, boolean verifyPadding(byte[] ciphertext) – returns whether the padding is right.The padding oraculum attack is implemented in decryptLastBlock method. The method decrypts last block of encrypted message: private String decryptLastBlock(PaddingOraculum oraculum, byte[] ciphertext) { // extract relevant part of the ciphertext byte[] ivAndBlock = getLastTwoBlocks(ciphertext, oraculum.getBlockSize()); // modified initial vector byte[] ivMod = new byte[oraculum.getBlockSize()]; Arrays.fill(ivMod, (byte) 0);// Start with last byte of the last block and // continue to the first byte. for (int i = oraculum.getBlockSize()-1; i >= 0; i--) { // add padding to the initial vector int expectedPadding = oraculum.getBlockSize() - i; xorPad(ivMod, expectedPadding);// loop through possible values of ivModification[i] for (ivMod[i] = -128; ivMod[i] < 127; ivMod[i]++) { // create fake message and verify its padding byte[] modifiedCiphertext = replaceBeginning(ivAndBlock, ivMod); if (oraculum.verifyPadding(modifiedCiphertext)) { // we can stop looping // the ivModification[i] = // = solution ^ expectedPadding ^ ivAndBlock[i] break; } }// remove the padding from the initial vector xorPad(ivMod, expectedPadding); }// modified initial vector now contains the solution xor // original initial vector String result = ""; for (int i = 0; i < ivMod.length; i++) { ivMod[i] = (byte) (ivMod[i] ^ ivAndBlock[i]); result += (char) ivMod[i]; } return result; }Our sample project contains two test cases. One encrypts message with AES-CBC and then uses the padding oraculum to the last block of the ciphertext. The other do the same thing with Blowfish-CBC. Decrypt Blowfish-CBC test case: @Test public void testPaddingOracle_Blowfish() { String message = "secret message!";PaddingOraculum oraculum = new PaddingOraculum( new BlowfishCipherService()); //Oraculum encrypts the message with a secret key. byte[] ciphertext = oraculum.encrypt(message); //use oraculum to decrypt the message String result = decryptLastBlock(oraculum, ciphertext); //the original message had padding 1 assertEquals("essage!"+(char)1, result); }Resources Additional related resources:Free online Stanford crypto class. The original paper with padding oracle attack from 2002. A good alternative explanation of padding oracle attack. A beast attack on CBC explained. It is based on padding oracle attack. Stack exchange thread on common cryptography mistakes.End No cipher provides absolute safety against all possible attacks. Instead, they provide protection only against well defined classes of attacks. Ciphers are secure only as long as the potential threat to the system matches the cipher strength. Protection against an active attack can be done in two ways:Make an active attack impossible by design. Use an authenticated encryption.Using an authenticated encryption is arguably easier and should be the preferred option. Ruling out the active attacker is error prone and more risky. All code sample used in this post are available on Github. Reference: Secure Encryption in Java from our JCG partner Maria Jurcovicova at the This is Stuff blog....
java-logo

Threading stories: ThreadLocal in web applications

This week I spend reasonable time to eliminate all our ThreadLocal variables in our web applications. The reason was that they created classloader leaks and we coudn’t undeploy our applications properly anymore. Classloader leaks happen when a GC root keeps referencing an application object after the application was undeployed. If an application object is still referenced after undeploy, then the whole class loader can’t be garbage collected cause the considered object references your applications class file which in turn references the classloader. This will cause an OutOfMemoryError after you’ve undeployed and redeployed a couple of times. ThreadLocal is one classic candidate that can easily create classloader leaks in web applications. The server is managing its threads in a pool. These threads live longer then your web application. In fact they don’t die at all until the underlying JVM dies. Now, if you put a ThreadLocal in a pooled thread that references an object of your class you *must* be careful. You need to make sure that this variable is removed again using ThreadLocal.remove(). The issue in web applications is: where is the right place to safely remove ThreadLocal variables? Also, you may not want to modify that “removing code” every time a colleague decided to add another ThreadLocal to the managed threads. We’ve developed a wrapper class around thread local that keeps all the thread local variables in one single ThreadLocal variable. Here is the code. public class ThreadLocalUtil {private final static ThreadLocal<ThreadVariables> THREAD_VARIABLES = new ThreadLocal<ThreadVariables>() {/** * @see java.lang.ThreadLocal#initialValue() */ @Override protected ThreadVariables initialValue() { return new ThreadVariables(); } };public static Object getThreadVariable(String name) { return THREAD_VARIABLES.get().get(name); }public static Object getThreadVariable(String name, InitialValue initialValue) { Object o = THREAD_VARIABLES.get().get(name); if (o == null) { THREAD_VARIABLES.get().put(name, initialValue.create()); return getThreadVariable(name); } else { return o; } }public static void setThreadVariable(String name, Object value) { THREAD_VARIABLES.get().put(name, value); }public static void destroy() { THREAD_VARIABLES.remove(); } }public class ThreadVariables extends HashMap<String, Object> { }public abstract class InitialValue {public abstract Object create();}The advantage of the utility class is that no developer needs to manage the thread local variable lifecycle individually. The class puts all the thread locals in one map of variables. The destroy() method can be invoked where you can safely remove all thread locals in your web application. In our case thats a ServletRequestListener -> requestDestroyed() method. You will also need to place finally blocks elsewhere. Typical places are near the HttpServlet, in the init(), doPost(), doGet() methods. This may remove all thread locals in the pooled worker threads after the request is done or an exception is thrown unexpectedly. Sometimes it happens that the main thread of the server leaks thread local variables. If that is the case you need to find the right places where to call the ThreadLocalUtil -> destroy() method. To do that figure out where the main thread actually *creates* the thread variables. You could use your debugger to do that. Many guys out there suggest to ommit ThreadLocal in web applications for several reasons. It can be very difficult to remove them in a pooled thread environment so that you can undeploy the applications safely. ThreadLocal variables can be useful, but it’s fair to consider other techniques before applying them. An alternative for web applications to carry request scope parameters is the HttpServletRequest. Many web frameworks allow for generic request parameter access as well as request/session attribute access, without ties to the native Servlet/Portlet API. Also many framework support request scoped beans to be injected into an object tree using dependency injection. All these options fulfill most requirements and should be considered prior to using ThreadLocal. Reference: Threading stories: ThreadLocal in web applications from our JCG partner Niklas....
javafx-logo

JavaFX 2 GameTutorial Part 2

Introduction This is the second installment of a series of blog entries relating to a JavaFX 2 Game Tutorial. If you have not read Part 1 please see the introduction section of the JavaFX 2 Game Tutorial. To recap in Part 1, I mention some aspects of game play and a simple demo of a prototype spaceship (comprised of simple shapes) that is capable of navigating via the mouse. Disclaimer: This is a long tutorial so if you just want to run the demo just Click HERE. The demo is called Atom Smasher where you generate atoms (spheres) that collide. You may freeze the game to add more atoms. The objective is to have more than one atom alive and bouncing around. A text displays the current number of atoms floating around. Before beginning our discussion on a game loop I wanted to give you some background history about games and animation.History Back in the day (during the 80s-90s) many game programmers attempted to animate images has encountered the infamous screen flicker problem. This is where your sprites (graphic images) will often flash and make the game look quite awful. All monitors have a refresh rate where certain intervals the pixels will be redrawn (called vertical retrace CRTs). For example, if the refresh rate is 80 Hz it is approximately 80 times a second the screen is redrawn. If you are modifying things on the screen you can often be out ofsyncbecause of being in the middle of a refresh interval. What should you do about this? Well, actually there are two things that will help remedy this problem (double buffering & knowing when the cycle is occurring). Some clever developers created a technique called double buffering. Double buffering is a technique which consists of two surfaces where each takes turns on becoming the displayable surface and the other is an offscreen area (buffer surface). This technique is really a digital sleight of hand trick where the developer can pre calculate the sprites and their positions to be drawn on the offscreen surface. Once you are finished drawing on the offscreen buffer the code will switch it as the displayable surface. An important thing to point out is that we still have an issue due to the fact that we need to be notified when the refresh interval is about to begin the redraw process. In Java this ability is built in via the BufferStrategy API. So, where am I going with this? Sometimes explaining the past strategies will help us appreciate what we have today. Do we need to do this in JavaFX? Nope. Have no fear JavaFX is here! All of the issues thatI’vementioned are all taken care of for us by using JavaFX’s Scene graph API. However, most games will still use the old fashion way of animating graphics and updating the game world called the ‘Game Loop’. The Game Loop Simply put the game loop is responsible for updating sprites (graphics), checking collision, and cleanup. Older game loops will check for key and mouse events as part of the loop. Since JavaFX abstracts events to allow the Scene or individual nodes to handle events the ability to listen to low level events aren’t necessary in our game loop. Shown below is a source code snippet of a typical game loop which will update sprites, check collisions, and cleanup sprites at each cycle. You will notice the Duration object from JavaFX 2.x which represents 60 divided by 1000 milliseconds or 60 frames per second(FPS). Each frame will call the handle() method of the JavaFX’s EventHandler interface in order to update the game world. Hypothetically, I’ve create three methods updateSprites(), checkCollisions(), and cleanupSprites() that will be invoked to handle sprites in the game. final Duration oneFrameAmt = Duration.millis(1000/60); final KeyFrame oneFrame = new KeyFrame(oneFrameAmt, new EventHandler() {@Override public void handle(javafx.event.ActionEvent event) {// update actors updateSprites();// check for collision checkCollisions();// removed dead things cleanupSprites();} }); // oneFrame// sets the game world's game loop (Timeline) TimelineBuilder.create() .cycleCount(Animation.INDEFINITE) .keyFrames(oneFrame) .build() .play();The above code snippet is really all you need to create a simple game or animation. However, you may want to take things to the next level. You may want to create a game engine that can manage sprites and the state of the game world. Game Engine A game engine is a fancy name for a utility or library responsible for encapsulating the game world, running the game loop, managing sprites, physics, etc. This is essentially a small game framework that allows you to extend or reuse so you don’t have to reinvent the wheel when creating a 2D game from scratch. To fast forward I created a UML class diagram of a design of a game engine. Shown below is Figure 1 A JavaFX Game Engine Class diagram.Figure 1. A JavaFX 2 Game Engine DesignIn Figure 1 A JavaFX 2 Game Engine Design you will notice three classes a GameWorld, SpriteManager, and Sprite. The GameWorld class is responsible for initializing the game state, executing the game loop, updating sprites, handling sprite collisions, and cleaning up. Next is the SpriteManager class which in charge of managing sprites by adding, removing, and other house keeping for collisions. Lastly, is the Sprite class which is responsible for maintaining the state of an image (Actor). In a 2D world a sprite can contain the object’s velocity, rotation, scene node or image that eventually gets rendered at each cycle (key frame/frames per second). Just a quick reminder on UML notation:Plus symbol ‘+‘ denotes that a class member is public. Minus symbol ‘-‘ denotes that a class member isprivate Hash symbol ‘#‘ denotes that a class member is protected.GameWorld Below is the source code implementation of the GameWorld class. Click to expand. Later you will see a class diagram depicting a simple demo game that will extend the GameWorld class (see AtomSmasher). package carlfx.gameengine;import javafx.animation.Animation; import javafx.animation.KeyFrame; import javafx.animation.Timeline; import javafx.animation.TimelineBuilder; import javafx.event.ActionEvent; import javafx.event.EventHandler; import javafx.scene.Group; import javafx.scene.Scene; import javafx.stage.Stage; import javafx.util.Duration;/** * This application demonstrates a JavaFX 2.x Game Loop. * Shown below are the methods which comprise of the fundamentals to a * simple game loop in JavaFX: * * <strong>initialize()</strong> - Initialize the game world. * <strong>beginGameLoop()</strong> - Creates a JavaFX Timeline object containing the game life cycle. * <strong>updateSprites()</strong> - Updates the sprite objects each period (per frame) * <strong>checkCollisions()</strong> - Method will determine objects that collide with each other. * <strong>cleanupSprites()</strong> - Any sprite objects needing to be removed from play. * * @author cdea */ public abstract class GameWorld {/** The JavaFX Scene as the game surface */ private Scene gameSurface; /** All nodes to be displayed in the game window. */ private Group sceneNodes; /** The game loop using JavaFX's <code>Timeline</code> API.*/ private static Timeline gameLoop;/** Number of frames per second. */ private final int framesPerSecond;/** Title in the application window.*/ private final String windowTitle;/** * The sprite manager. */ private final SpriteManager spriteManager = new SpriteManager();/** * Constructor that is called by the derived class. This will * set the frames per second, title, and setup the game loop. * @param fps - Frames per second. * @param title - Title of the application window. */ public GameWorld(final int fps, final String title) { framesPerSecond = fps; windowTitle = title; // create and set timeline for the game loop buildAndSetGameLoop(); }/** * Builds and sets the game loop ready to be started. */ protected final void buildAndSetGameLoop() {final Duration oneFrameAmt = Duration.millis(1000/getFramesPerSecond()); final KeyFrame oneFrame = new KeyFrame(oneFrameAmt, new EventHandler() {@Override public void handle(javafx.event.ActionEvent event) {// update actors updateSprites();// check for collision checkCollisions();// removed dead things cleanupSprites();} }); // oneFrame// sets the game world's game loop (Timeline) setGameLoop(TimelineBuilder.create() .cycleCount(Animation.INDEFINITE) .keyFrames(oneFrame) .build()); }/** * Initialize the game world by update the JavaFX Stage. * @param primaryStage */ public abstract void initialize(final Stage primaryStage);/**Kicks off (plays) the Timeline objects containing one key frame * that simply runs indefinitely with each frame invoking a method * to update sprite objects, check for collisions, and cleanup sprite * objects. * */ public void beginGameLoop() { getGameLoop().play(); }/** * Updates each game sprite in the game world. This method will * loop through each sprite and passing it to the handleUpdate() * method. The derived class should override handleUpdate() method. * */ protected void updateSprites() { for (Sprite sprite:spriteManager.getAllSprites()){ handleUpdate(sprite); } }/** Updates the sprite object's information to position on the game surface. * @param sprite - The sprite to update. */ protected void handleUpdate(Sprite sprite) { }/** * Checks each game sprite in the game world to determine a collision * occurred. The method will loop through each sprite and * passing it to the handleCollision() * method. The derived class should override handleCollision() method. * */ protected void checkCollisions() { // check other sprite's collisions spriteManager.resetCollisionsToCheck(); // check each sprite against other sprite objects. for (Sprite spriteA:spriteManager.getCollisionsToCheck()){ for (Sprite spriteB:spriteManager.getAllSprites()){ if (handleCollision(spriteA, spriteB)) { // The break helps optimize the collisions // The break statement means one object only hits another // object as opposed to one hitting many objects. // To be more accurate comment out the break statement. break; } } } }/** * When two objects collide this method can handle the passed in sprite * objects. By default it returns false, meaning the objects do not * collide. * @param spriteA - called from checkCollision() method to be compared. * @param spriteB - called from checkCollision() method to be compared. * @return boolean True if the objects collided, otherwise false. */ protected boolean handleCollision(Sprite spriteA, Sprite spriteB) { return false; }/** * Sprites to be cleaned up. */ protected void cleanupSprites() { spriteManager.cleanupSprites(); }/** * Returns the frames per second. * @return int The frames per second. */ protected int getFramesPerSecond() { return framesPerSecond; }/** * Returns the game's window title. * @return String The game's window title. */ public String getWindowTitle() { return windowTitle; }/** * The game loop (Timeline) which is used to update, check collisions, and * cleanup sprite objects at every interval (fps). * @return Timeline An animation running indefinitely representing the game * loop. */ protected static Timeline getGameLoop() { return gameLoop; }/** * The sets the current game loop for this game world. * @param gameLoop Timeline object of an animation running indefinitely * representing the game loop. */ protected static void setGameLoop(Timeline gameLoop) { GameWorld.gameLoop = gameLoop; }/** * Returns the sprite manager containing the sprite objects to * manipulate in the game. * @return SpriteManager The sprite manager. */ protected SpriteManager getSpriteManager() { return spriteManager; }/** * Returns the JavaFX Scene. This is called the game surface to * allow the developer to add JavaFX Node objects onto the Scene. * @return */ public Scene getGameSurface() { return gameSurface; }/** * Sets the JavaFX Scene. This is called the game surface to * allow the developer to add JavaFX Node objects onto the Scene. * @param gameSurface The main game surface (JavaFX Scene). */ protected void setGameSurface(Scene gameSurface) { this.gameSurface = gameSurface; }/** * All JavaFX nodes which are rendered onto the game surface(Scene) is * a JavaFX Group object. * @return Group The root containing many child nodes to be displayed into * the Scene area. */ public Group getSceneNodes() { return sceneNodes; }/** * Sets the JavaFX Group that will hold all JavaFX nodes which are rendered * onto the game surface(Scene) is a JavaFX Group object. * @param sceneNodes The root container having many children nodes * to be displayed into the Scene area. */ protected void setSceneNodes(Group sceneNodes) { this.sceneNodes = sceneNodes; }}SpriteManager A sprite manager class is a helper class to assist the game loop to keep track of sprites. Normally a sprite manager will contain all sprites and each sprite contains a JavaFX Node that is displayed onto the Scene graph. Shown below is the source code. Click to expand. package carlfx.gameengine;import java.util.*;/** * Sprite manager is responsible for holding all sprite objects, and cleaning up * sprite objects to be removed. All collections are used by the JavaFX * application thread. During each cycle (animation frame) sprite management * occurs. This assists the user of the API to not have to create lists to * later be garbage collected. Should provide some performance gain. * @author cdea */ public class SpriteManager { /** All the sprite objects currently in play */ private final static List GAME_ACTORS = new ArrayList<>();/** A global single threaded list used to check collision against other * sprite objects. */ private final static List CHECK_COLLISION_LIST = new ArrayList<>();/** A global single threaded set used to cleanup or remove sprite objects * in play. */ private final static Set CLEAN_UP_SPRITES = new HashSet<>();/** */ public List getAllSprites() { return GAME_ACTORS; }/** * VarArgs of sprite objects to be added to the game. * @param sprites */ public void addSprites(Sprite... sprites) { GAME_ACTORS.addAll(Arrays.asList(sprites)); }/** * VarArgs of sprite objects to be removed from the game. * @param sprites */ public void removeSprites(Sprite... sprites) { GAME_ACTORS.removeAll(Arrays.asList(sprites)); }/** Returns a set of sprite objects to be removed from the GAME_ACTORS. * @return CLEAN_UP_SPRITES */ public Set getSpritesToBeRemoved() { return CLEAN_UP_SPRITES; }/** * Adds sprite objects to be removed * @param sprites varargs of sprite objects. */ public void addSpritesToBeRemoved(Sprite... sprites) { if (sprites.length > 1) { CLEAN_UP_SPRITES.addAll(Arrays.asList((Sprite[]) sprites)); } else { CLEAN_UP_SPRITES.add(sprites[0]); } }/** * Returns a list of sprite objects to assist in collision checks. * This is a temporary and is a copy of all current sprite objects * (copy of GAME_ACTORS). * @return CHECK_COLLISION_LIST */ public List getCollisionsToCheck() { return CHECK_COLLISION_LIST; }/** * Clears the list of sprite objects in the collision check collection * (CHECK_COLLISION_LIST). */ public void resetCollisionsToCheck() { CHECK_COLLISION_LIST.clear(); CHECK_COLLISION_LIST.addAll(GAME_ACTORS); }/** * Removes sprite objects and nodes from all * temporary collections such as: * CLEAN_UP_SPRITES. * The sprite to be removed will also be removed from the * list of all sprite objects called (GAME_ACTORS). */ public void cleanupSprites() {// remove from actors list GAME_ACTORS.removeAll(CLEAN_UP_SPRITES);// reset the clean up sprites CLEAN_UP_SPRITES.clear(); } }Sprite The Sprite class represents an image or node to be displayed onto the JavaFX Scene graph. In a 2D game a sprite will contain additional information such as its velocity for the object as it moves across the scene area. The game loop will call the update() and collide() method at every interval of a key frame. Shown below is the source code. Click to expand. package carlfx.gameengine;import java.util.ArrayList; import java.util.List; import javafx.animation.Animation; import javafx.scene.Node;/** * The Sprite class represents a image or node to be displayed. * In a 2D game a sprite will contain a velocity for the image to * move across the scene area. The game loop will call the update() * and collide() method at every interval of a key frame. A list of * animations can be used during different situations in the game * such as rocket thrusters, walking, jumping, etc. * @author cdea */ public abstract class Sprite {/** Animation for the node */ public List animations = new ArrayList<>();/** Current display node */ public Node node;/** velocity vector x direction */ public double vX = 0;/** velocity vector y direction */ public double vY = 0;/** dead? */ public boolean isDead = false;/** * Updates this sprite object's velocity, or animations. */ public abstract void update();/** * Did this sprite collide into the other sprite? * * @param other - The other sprite. * @return */ public boolean collide(Sprite other) { return false; } }JavaFX 2 Game Loop Demo – Atom Smasher Whew! If you’ve got this far you are one brave soul. Let’s take a small break and try out the demo I created using the game engine above. Shown below is a Java Webstart button to launch the game demo. Later, you will see the design and source code detailing how it was created. Requirements:Java 7 or later JavaFX 2.0.2 2.1 or later Windows XP or later (Should be available soon for Linux/MacOS)DemoGameLoopPart2 Design Below is a class diagram of the game demo called Atom Smasher which uses the game engine framework mentioned earlier. Shown below is Figure 2 Atom Smasher Class Diagram.Figure 2. Atom Smasher Class DiagramGameLoopPart2 The GameLoopPart2 is the driver or main JavaFX application that runs the game. This creates a GameWorld object to be initialized and starts the game loop. Shown below is the source code. Click to expand. package carlfx;import carlfx.gameengine.GameWorld; import javafx.application.Application; import javafx.stage.Stage;/** * The main driver of the game. * @author cdea */ public class GameLoopPart2 extends Application {GameWorld gameWorld = new AtomSmasher(60, "JavaFX 2 GameTutorial Part 2 - Game Loop"); /** * @param args the command line arguments */ public static void main(String[] args) { launch(args); }@Override public void start(Stage primaryStage) { // setup title, scene, stats, controls, and actors. gameWorld.initialize(primaryStage);// kick off the game loop gameWorld.beginGameLoop();// display window primaryStage.show(); }}AtomSmasher AtomSmasher is a derived class of the GameWorld class. It creates many spheres that animate with random velocities, colors and positions. Button controls lets the user generate more ‘atoms’ (JavaFX Circle nodes). As each atom collides with one another they will invoke the implode() method that produces a fade transition animation. You will notice how easy it is to implement this game by simply implementing initialize(), handleUpdate(), handleCollision(), and cleanupSprites() methods. Once implemented the game engine does the rest. The initialize() method creates the button controls for the user. To update the sprites positions or change the game state you will implement the handleUpdate() method. To compare all sprites if they have collided with one another you will implement the handleCollision(). The last part of the game loop’s life cycle is cleaning up sprites. Cleaning up means updating the sprite manger and updating the JavaFX Scene (removing nodes). Shown below is the source code. Click to expand. package carlfx;import carlfx.gameengine.GameWorld; import carlfx.gameengine.Sprite; import java.util.Random; import javafx.animation.Timeline; import javafx.event.EventHandler; import javafx.scene.Group; import javafx.scene.Scene; import javafx.scene.control.ButtonBuilder; import javafx.scene.control.Label; import javafx.scene.input.MouseEvent; import javafx.scene.layout.HBoxBuilder; import javafx.scene.layout.VBox; import javafx.scene.layout.VBoxBuilder; import javafx.scene.paint.Color; import javafx.scene.shape.Circle; import javafx.stage.Stage; import static javafx.animation.Animation.Status.RUNNING; import static javafx.animation.Animation.Status.STOPPED;/** * This is a simple game world simulating a bunch of spheres looking * like atomic particles colliding with each other. When the game loop begins * the user will notice random spheres (atomic particles) floating and * colliding. The user is able to press a button to generate more * atomic particles. Also, the user can freeze the game. * * @author cdea */ public class AtomSmasher extends GameWorld { /** Read only field to show the number of sprite objects are on the field*/ private final static Label NUM_SPRITES_FIELD = new Label();public AtomSmasher(int fps, String title){ super(fps, title); }/** * Initialize the game world by adding sprite objects. * @param primaryStage */ @Override public void initialize(final Stage primaryStage) { // Sets the window title primaryStage.setTitle(getWindowTitle());// Create the scene setSceneNodes(new Group()); setGameSurface(new Scene(getSceneNodes(), 640, 580)); primaryStage.setScene(getGameSurface());// Create many spheres generateManySpheres(150);// Display the number of spheres visible. // Create a button to add more spheres. // Create a button to freeze the game loop. final Timeline gameLoop = getGameLoop(); VBox stats = VBoxBuilder.create() .spacing(5) .translateX(10) .translateY(10) .children(HBoxBuilder.create() .spacing(5) .children(new Label("Number of Particles: "), // show no. particles NUM_SPRITES_FIELD).build(),// button to build more spheres ButtonBuilder.create() .text("Regenerate") .onMousePressed(new EventHandler() { @Override public void handle(MouseEvent arg0) { generateManySpheres(150); }}).build(),// button to freeze game loop ButtonBuilder.create() .text("Freeze/Resume") .onMousePressed(new EventHandler() {@Override public void handle(MouseEvent arg0) { switch (gameLoop.getStatus()) { case RUNNING: gameLoop.stop(); break; case STOPPED: gameLoop.play(); break; } }}).build() ).build(); // (VBox) stats on children// lay down the controls getSceneNodes().getChildren().add(stats); }/** * Make some more space spheres (Atomic particles) */ private void generateManySpheres(int numSpheres) { Random rnd = new Random(); Scene gameSurface = getGameSurface(); for (int i=0; i (gameSurface.getWidth() - (circle.getRadius() * 2))) { newX = gameSurface.getWidth() - (circle.getRadius() * 2); }// check for the bottom of screen the height newY is greater than height // minus radius times 2(height of sprite) double newY = rnd.nextInt((int) gameSurface.getHeight()); if (newY > (gameSurface.getHeight() - (circle.getRadius() * 2))) { newY = gameSurface.getHeight() - (circle.getRadius() * 2); }circle.setTranslateX(newX); circle.setTranslateY(newY); circle.setVisible(true); circle.setId(b.toString());// add to actors in play (sprite objects) getSpriteManager().addSprites(b);// add sprite's getSceneNodes().getChildren().add(0, b.node);} }/** * Each sprite will update it's velocity and bounce off wall borders. * @param sprite - An atomic particle (a sphere). */ @Override protected void handleUpdate(Sprite sprite) { if (sprite instanceof Atom) { Atom sphere = (Atom) sprite;// advance the spheres velocity sphere.update();// bounce off the walls when outside of boundaries if (sphere.node.getTranslateX() > (getGameSurface().getWidth() - sphere.node.getBoundsInParent().getWidth()) || sphere.node.getTranslateX() < 0 ) { sphere.vX = sphere.vX * -1; } if (sphere.node.getTranslateY() > getGameSurface().getHeight()- sphere.node.getBoundsInParent().getHeight() || sphere.node.getTranslateY() < 0) { sphere.vY = sphere.vY * -1; } } }/** * How to handle the collision of two sprite objects. Stops the particle * by zeroing out the velocity if a collision occurred. * @param spriteA * @param spriteB * @return */ @Override protected boolean handleCollision(Sprite spriteA, Sprite spriteB) { if (spriteA.collide(spriteB)) { ((Atom)spriteA).implode(this); ((Atom)spriteB).implode(this); getSpriteManager().addSpritesToBeRemoved(spriteA, spriteB); return true; } return false; }/** * Remove dead things. */ @Override protected void cleanupSprites() { // removes from the scene and backend store super.cleanupSprites();// let user know how many sprites are showing. NUM_SPRITES_FIELD.setText(String.valueOf(getSpriteManager().getAllSprites().size()));} }Atom The Atom class extends from the Sprite class. An atom is a sprite that appears like a spherical object that moves across the scene. An atom will have a random radius, color, and velocity. As each atom sprite collides with another atom they will animate a fade transition (the implode() method). Shown below is the source code. Click to expand. package carlfx;import carlfx.gameengine.GameWorld; import carlfx.gameengine.Sprite; import javafx.animation.FadeTransitionBuilder; import javafx.event.ActionEvent; import javafx.event.EventHandler; import javafx.scene.paint.Color; import javafx.scene.paint.RadialGradient; import javafx.scene.paint.RadialGradientBuilder; import javafx.scene.paint.Stop; import javafx.scene.shape.Circle; import javafx.scene.shape.CircleBuilder; import javafx.util.Duration;/** * A spherical looking object (Atom) with a random radius, color, and velocity. * When two atoms collide each will fade and become removed from the scene. The * method called implode() implements a fade transition effect. * * @author cdea */ public class Atom extends Sprite {public Atom(double radius, Color fill) { Circle sphere = CircleBuilder.create() .centerX(radius) .centerY(radius) .radius(radius) .cache(true) .build();RadialGradient rgrad = RadialGradientBuilder.create() .centerX(sphere.getCenterX() - sphere.getRadius() / 3) .centerY(sphere.getCenterY() - sphere.getRadius() / 3) .radius(sphere.getRadius()) .proportional(false) .stops(new Stop(0.0, fill), new Stop(1.0, Color.BLACK)) .build();sphere.setFill(rgrad);// set javafx node to a circle node = sphere;}/** * Change the velocity of the atom particle. */ @Override public void update() { node.setTranslateX(node.getTranslateX() + vX); node.setTranslateY(node.getTranslateY() + vY); }@Override public boolean collide(Sprite other) { if (other instanceof Atom) { return collide((Atom)other); } return false; }/** * When encountering another Atom to determine if they collided. * @param other Another atom * @return boolean true if this atom and other atom has collided, * otherwise false. */ private boolean collide(Atom other) {// if an object is hidden they didn't collide. if (!node.isVisible() || !other.node.isVisible() || this == other) { return false; }// determine it's size Circle otherSphere = other.getAsCircle(); Circle thisSphere = getAsCircle(); double dx = otherSphere.getTranslateX() - thisSphere.getTranslateX(); double dy = otherSphere.getTranslateY() - thisSphere.getTranslateY(); double distance = Math.sqrt( dx * dx + dy * dy ); double minDist = otherSphere.getRadius() + thisSphere.getRadius() + 3;return (distance < minDist); }/** * Returns a node casted as a JavaFX Circle shape. * @return Circle shape representing JavaFX node for convenience. */ public Circle getAsCircle() { return (Circle) node; }/** * Animate an implosion. Once done remove from the game world * @param gameWorld - game world */ public void implode(final GameWorld gameWorld) { vX = vY = 0; FadeTransitionBuilder.create() .node(node) .duration(Duration.millis(300)) .fromValue(node.getOpacity()) .toValue(0) .onFinished(new EventHandler() { @Override public void handle(ActionEvent arg0) { isDead = true; gameWorld.getSceneNodes().getChildren().remove(node); } }) .build() .play(); } }Conclusion Hopefully you’ve got a chance to understand the fundamentals of a gaming loop and later apply the knowledge by implementing a robust game engine. Although, I briefly mention collision I am saving that for Part 4 of these tutorials. Please stay tuned for Part 3 where we will get into input using the keyboard or mouse. Feel free to experiment. Let me know what you come up with. To obtain the source code please download the link to a jar file below by using the ‘Save link As‘ option in your browser. If you are on a Windows system you can change the extension from ‘jar‘ to ‘zip‘ to be easily expanded. It will contain a directory ‘src‘ with the source code. The source code location: http://www.jroller.com/carldea/resource/javafx2.0_games/part2source_code.jar The published version of the source code is at theGitHub called(JFXGen)for you to clone and fork to your hearts content (It’s there for you to use for your own projects). Enjoy. https://github.com/carldea/JFXGen git clonegit@github.com:carldea/JFXGen.git Reference: JavaFX 2 GameTutorial Part 2 from our JCG partner Carl Dea at the Carl’s FX Blog blog....
javaone-logo

JavaOne 2012 Analysis – Submitted Proposals and Speaker Distribution

Beginning some time last year I started to have a closer look at conferences and their speakers. My main interest was to find out who was speaking how often. One conference was missing in this analysis because I really was not sure what can be published without breaking the confidentiality of the information. Being a member of the program committee for the second time this year and seeing all those wonderful sessions forced me to take another look at it and finally today I have at least some percentages to show to you. A big thank you goes out to Oracle’s Sharat Chander for giving the permission to do that! Based on the complete data for what has been submitted to JavaOne 2012 in San Francisco I will let you have a look at types, distribution and speakers. Every number given here is a percentage and the numbers behind them are still confidential. And again: This is an analysis of the complete submitted data. This doesn’t tell you anything about what is going to be selected! The voting is still ongoing and the different program committees are hard at work reviewing every single proposal. Submission Types First of all let’s look at the general distribution of submitted types independently of any track. Speakers could select any of five different types for their submission. The classic session, a BoF (Birds of a feather) a tutorial, a HoL (Hands on Lab) and for the first time this year a community keynote. Not a big surprise that most of the submissions are sessions (70,14%). Second most proposed content are BoFs. Followed by tutorials, HoLs and some community keynote proposals. Even if this sounds very concrete, there is still some motion in here. Some BoFs might become sessions and the other way around.Submission TypesSubmissions per Track Next most interesting figure is the general distribution of submissions per track. Seven tracks are there to chose from. Starting with the Core Java Platform and finishing with Java on Card and Devices. It is good to see a very evenly distributed number of proposals for every track. Lead by the Development Tools and Techniques track (24,15%) both Java ME, Java Card Embedded and Devices (8,21%) and Emerging Languages (5,86%) are the bottom end. Very few proposals are moved around from track to track during the voting process but it happens. I don’t expect the final distribution to differ heavily from the one shown below.Distribution per TrackInternal vs. External Submissions The no 1 question discussed a lot in the past is the number of sessions given by Oracle employees. even if I would love to make an educated guess here, anything I can show you is the distribution with regards to the proposals. I have looked at the first speaker of every session and assigned it an internal or external flag (yes, that took some time ;)). More than 2/3rd (71%) of the submissions come from external (aka non-Oracle)speakers. Even if I have seen some combined proposals also this is a clear sign, that JavaOne is a community driven conference.External vs. Internal SpeakersBut where exactly is Oracle jumping in? Are there differences in submissions per track if we look at the internal speakers? Internal proposals have a stronger focus on Embedded Java, the Core Platform and JavaFX compared with the external submissions.Submission Distribution by internal speakersSubmission Distribution by external speakersWhat do we learn from all that? JavaOne is going to be a great, community driven conference with a lot of awesome sessions to come! If you haven’t done so take a look and register for it! The final program is going to be announced in a few weeks and there still is plenty of time to find a flight and a hotel near by. Reference: JavaOne 2012 Analysis – Submitted Proposals and Speaker Distribution from our JCG partner Markus Eisele at the Enterprise Software Development with Java blog....
Java Code Geeks and all content copyright © 2010-2014, Exelixis Media Ltd | Terms of Use | Privacy Policy
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.

Sign up for our Newsletter

20,709 insiders are already enjoying weekly updates and complimentary whitepapers! Join them now to gain exclusive access to the latest news in the Java world, as well as insights about Android, Scala, Groovy and other related technologies.

As an extra bonus, by joining you will get our brand new e-books, published by Java Code Geeks and their JCG partners for your reading pleasure! Enter your info and stay on top of things,

  • Fresh trends
  • Cases and examples
  • Research and insights
  • Two complimentary e-books