Featured FREE Whitepapers

What's New Here?


TeamCity artifacts: HTTP, Ant, Gradle and Maven

In how many ways can you retrieve TeamCity artifacts? I say plenty to choose from! If you’re in a world of Java build tools then you can use plain HTTP request, Ant + Ivy, Gradle and Maven to download and use binaries produced by TeamCity build configurations. How? Read on. Build Configuration “id” Before you retrieve artifacts of any build configuration you need to know its "id" which can be seen in a browser when corresponding configuration is browsed. Let’s take IntelliJ IDEA Community Edition project hosted at teamcity.jetbrains.com as an example. Its “Community Dist” build configuration provides a number of artifacts which we’re going to play with. And as can be seen on the screenshot below, its "id" is "bt343".HTTP Anonymous HTTP access is probably the easiest way to fetch TeamCity artifacts, the URL to do so is: http://server/guestAuth/repository/download/<btN>/<buildNumber>/<artifactName> Fot this request to work 3 parameters need to be specified:btN Build configuration "id", as mentioned above.buildNumber Build number or one of predefined constants: "lastSuccessful", "lastPinned", or "lastFinished". For example, you can download periodic IDEA builds from last successful TeamCity execution.artifactName Name of artifact like "ideaIC-118.SNAPSHOT.win.zip". Can also take a form of "artifactName!archivePath" for reading archive’s content, like IDEA’s build file. You can get a list of all artifacts produced in a certain build by requesting a special "teamcity-ivy.xml" artifact generated by TeamCity.Ant + Ivy All artifacts published to TeamCity are accompanied by "teamcity-ivy.xml" Ivy descriptor, effectively making TeamCity an Ivy repository. The code below downloads "core/annotations.jar" from IDEA distribution to "download/ivy" directory: "ivyconf.xml" <ivysettings> <settings defaultResolver='teamcity-repo'/> <resolvers> <url name='teamcity-repo' alwaysCheckExactRevision='yes' checkmodified='true'> <ivy pattern='http://teamcity.jetbrains.com/guestAuth/repository/download/[module]/[revision]/teamcity-ivy.xml'/> <artifact pattern='http://teamcity.jetbrains.com/guestAuth/repository/download/[module]/[revision]/[artifact](.[ext])'/> </url> </resolvers> </ivysettings> "ivy.xml" <ivy-module version="1.3"> <info organisation="com.jetbrains" module="idea"/> <dependencies> <dependency org="org" name="bt343" rev="lastSuccessful"> <include name="core/annotations" ext="jar"/> </dependency> </dependencies> </ivy-module> "build.xml" <project name="teamcity-download" default="download" xmlns:ivy="antlib:org.apache.ivy.ant"> <target name="download" xmlns:ivy="antlib:org.apache.ivy.ant"> <taskdef uri="antlib:org.apache.ivy.ant" resource="org/apache/ivy/ant/antlib.xml"/> <ivy:configure file = "${basedir}/ivyconf.xml"/> <ivy:resolve file = "${basedir}/ivy.xml"/> <ivy:retrieve pattern = "${basedir}/download/ivy/[artifact].[ext]"/> </target> </project>Gradle Identically to Ivy example above it is fairly easy to retrieve TeamCity artifacts with Gradle due to its built-in Ivy support. In addition to downloading the same jar file to "download/gradle" directory with a custom Gradle task let’s use it as "compile" dependency for our Java class, importing IDEA’s @NotNull annotation: "Test.java" import org.jetbrains.annotations.NotNull;public class Test { private final String data; public Test ( @NotNull String data ){ this.data = data; } }"build.gradle" apply plugin: 'java'repositories { ivy { ivyPattern 'http://teamcity.jetbrains.com/guestAuth/repository/download/[module]/[revision]/teamcity-ivy.xml' artifactPattern 'http://teamcity.jetbrains.com/guestAuth/repository/download/[module]/[revision]/[artifact](.[ext])' } }dependencies { compile ( 'org:bt343:lastSuccessful' ){ artifact { name = 'core/annotations' type = 'jar' } } }task copyJar( type: Copy ) { from configurations.compile into "${ project.projectDir }/download/gradle" }Maven The best way to use Maven with TeamCity is by setting up an Artifactory repository manager and its TeamCity plugin. This way artifacts produced by your builds are nicely deployed to Artifactory and can be served from there as from any other remote Maven repository. However, you can still use TeamCity artifacts in Maven without any additional setups. "ivy-maven-plugin" bridges two worlds allowing you to plug Ivy resolvers into Maven’s runtime environment, download dependencies required and add them to corresponding "compile" or "test" scopes. Let’s compile the same Java source from the Gradle example but using Maven this time. "pom.xml" <?xml version="1.0" encoding="UTF-8"?><project xmlns = "http://maven.apache.org/POM/4.0.0" xmlns:xsi = "http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation = "http://maven.apache.org/POM/4.0.0http://maven.apache.org/maven-v4_0_0.xsd"><modelVersion>4.0.0</modelVersion> <groupId>com.test</groupId> <artifactId>maven</artifactId> <packaging>jar</packaging> <version>0.1-SNAPSHOT</version> <name>[${project.groupId}:${project.artifactId}:${project.version}]</name> <description>Ivy Maven plugin example</description><build> <plugins> <plugin> <groupId>com.github.goldin</groupId> <artifactId>ivy-maven-plugin</artifactId> <version>0.2.5</version> <executions> <execution> <id>get-ivy-artifacts</id> <goals> <goal>ivy</goal> </goals> <phase>initialize</phase> <configuration> <ivyconf>${project.basedir}/ivyconf.xml</ivyconf> <ivy>${project.basedir}/ivy.xml</ivy> <dir>${project.basedir}/download/maven</dir> <scope>compile</scope> </configuration> </execution> </executions> </plugin> </plugins> </build> </project> When this plugin runs it resolves IDEA annotations artifact using the same "ivyconf.xml" and "ivy.xml" files we’ve seen previously, copies it to "download/maven" directory and adds to "compile" scope so our Java sources can compile. GitHub Project All examples demonstrated are available in my GitHub project. Feel free to clone and run it: git clone git://github.com/evgeny-goldin/teamcity-download-examples.git cd teamcity-download-examples chmod +x run.sh dist/ant/bin/ant gradlew dist/maven/bin/mvn ./run.shResources The links below can provide you with more details:TeamCity – Patterns For Accessing Build Artifacts TeamCity – Accessing Server by HTTP TeamCity – Configuring Artifact Dependencies Using Ant Build Script Gradle – Ivy repositories "ivy-maven-plugin"That’s it, you’ve seen it – TeamCity artifacts are perfectly accessible using either of 4 ways: direct HTTP access, Ant + Ivy, Gradle or Maven. Which one do you use? Let me know! Reference: Get TeamCity artifacts using HTTP, Ant, Gradle and Maven from our JCG partner Evgeny Goldin at the Goldin++ blog....

Load or Save Image using Hibernate – MySQL

This tutorial will walk you throughout how to save and load an image from database (MySQL) using Hibernate. Requirements For this sampel project, we are going to use:Eclipse IDE (you can use your favorite IDE); MySQL(you can use any other database, make sure to change the column type if required); Hibernate jars and dependencies (you can download the sample project with all required jars); JUnit - for testing (jar also included in the sample project).PrintScreen When we finish implementing this sample projeto, it should look like this:Database ModelBefore we get started with the sample projet, we have to run this sql script into MySQL: DROP SCHEMA IF EXISTS `blog` ; CREATE SCHEMA IF NOT EXISTS `blog` DEFAULT CHARACTER SET latin1 COLLATE latin1_swedish_ci ; USE `blog` ;-- ----------------------------------------------------- -- Table `blog`.`BOOK` -- ----------------------------------------------------- DROP TABLE IF EXISTS `blog`.`BOOK` ;CREATE TABLE IF NOT EXISTS `blog`.`BOOK` ( `BOOK_ID` INT NOT NULL AUTO_INCREMENT , `BOOK_NAME` VARCHAR(45) NOT NULL , `BOOK_IMAGE` MEDIUMBLOB NOT NULL , PRIMARY KEY (`BOOK_ID`) ) ENGINE = InnoDB;This script will create a table BOOK, which we are going to use in this tutorial. Book POJO We are going to use a simple POJO in this project. A Book has an ID, a name and an image, which is represented by an array of bytes. As we are going to persist an image into the database, we have to use the BLOB type. MySQLhas some variations of BLOBs, you can check the difference between them here. In this example, we are going to use the Medium Blob, which can store L+ 3 bytes, whereL< 2^24. Make sure you do not forget to add the column definition on the Column annotation. package com.loiane.model;import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.Id; import javax.persistence.Lob; import javax.persistence.Table;@Entity @Table(name="BOOK") public class Book {@Id @GeneratedValue @Column(name="BOOK_ID") private long id;@Column(name="BOOK_NAME", nullable=false) private String name;@Lob @Column(name="BOOK_IMAGE", nullable=false, columnDefinition="mediumblob") private byte[] image;public long getId() { return id; }public void setId(long id) { this.id = id; }public String getName() { return name; }public void setName(String name) { this.name = name; }public byte[] getImage() { return image; }public void setImage(byte[] image) { this.image = image; } }Hibernate Config This configuration file contains the required info used to connect to the database. <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE hibernate-configuration PUBLIC "-//Hibernate/Hibernate Configuration DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd"> <hibernate-configuration> <session-factory> <property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property> <property name="hibernate.connection.url">jdbc:mysql://localhost/blog</property> <property name="hibernate.connection.username">root</property> <property name="hibernate.connection.password">root</property> <property name="hibernate.dialect">org.hibernate.dialect.MySQLDialect</property> <property name="connection.pool_size">1</property> <property name="show_sql">true</property> </session-factory> </hibernate-configuration>Hibernate Util The HibernateUtil class helps in creating the SessionFactory from the Hibernate configuration file. package com.loiane.hibernate;import org.hibernate.SessionFactory; import org.hibernate.cfg.AnnotationConfiguration;import com.loiane.model.Book;public class HibernateUtil {private static final SessionFactory sessionFactory;static { try { sessionFactory = new AnnotationConfiguration() .configure() .addPackage("com.loiane.model") //the fully qualified package name .addAnnotatedClass(Book.class) .buildSessionFactory();} catch (Throwable ex) { System.err.println("Initial SessionFactory creation failed." + ex); throw new ExceptionInInitializerError(ex); } }public static SessionFactory getSessionFactory() { return sessionFactory; } }DAO In this class, we created two methods: one to save a Book instance into the database and another one to load a Book instance from the database. package com.loiane.dao;import org.hibernate.HibernateException; import org.hibernate.Session; import org.hibernate.Transaction;import com.loiane.hibernate.HibernateUtil; import com.loiane.model.Book;public class BookDAOImpl {/** * Inserts a row in the BOOK table. * Do not need to pass the id, it will be generated. * @param book * @return an instance of the object Book */ public Book saveBook(Book book) { Session session = HibernateUtil.getSessionFactory().openSession(); Transaction transaction = null; try { transaction = session.beginTransaction(); session.save(book); transaction.commit(); } catch (HibernateException e) { transaction.rollback(); e.printStackTrace(); } finally { session.close(); } return book; }/** * Delete a book from database * @param bookId id of the book to be retrieved */ public Book getBook(Long bookId) { Session session = HibernateUtil.getSessionFactory().openSession(); try { Book book = (Book) session.get(Book.class, bookId); return book; } catch (HibernateException e) { e.printStackTrace(); } finally { session.close(); } return null; } }Test To test it, first we need to create a Book instance and set an image to the image attribute. To do so, we need to load an image from the hard drive, and we are going to use the one located in the images folder. Then we can call the DAO class and save into the database. Then we can try to load the image. Just to make sure it is the same image we loaded, we are going to save it in the hard drive. package com.loiane.test;import static org.junit.Assert.assertNotNull;import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream;import org.junit.AfterClass; import org.junit.BeforeClass; import org.junit.Test;import com.loiane.dao.BookDAOImpl; import com.loiane.model.Book;public class TestBookDAO {private static BookDAOImpl bookDAO;@BeforeClass public static void runBeforeClass() { bookDAO = new BookDAOImpl(); }@AfterClass public static void runAfterClass() { bookDAO = null; }/** * Test method for {@link com.loiane.dao.BookDAOImpl#saveBook()}. */ @Test public void testSaveBook() {//File file = new File("images\\extjsfirstlook.jpg"); //windows File file = new File("images/extjsfirstlook.jpg"); byte[] bFile = new byte[(int) file.length()];try { FileInputStream fileInputStream = new FileInputStream(file); fileInputStream.read(bFile); fileInputStream.close(); } catch (Exception e) { e.printStackTrace(); }Book book = new Book(); book.setName("Ext JS 4 First Look"); book.setImage(bFile);bookDAO.saveBook(book);assertNotNull(book.getId()); }/** * Test method for {@link com.loiane.dao.BookDAOImpl#getBook()}. */ @Test public void testGetBook() {Book book = bookDAO.getBook((long) 1);assertNotNull(book);try{ //FileOutputStream fos = new FileOutputStream("images\\output.jpg"); //windows FileOutputStream fos = new FileOutputStream("images/output.jpg"); fos.write(book.getImage()); fos.close(); }catch(Exception e){ e.printStackTrace(); } } }To verify if it was really saved, let’s check the table Book:and if we right click…and choose to see the image we just saved, we will see it:Source CodeDownload You can download the complete source code (or fork/clone the project – git)from: Github: https://github.com/loiane/hibernate-image-example BitBucket: https://bitbucket.org/loiane/hibernate-image-example/downloads Happy Coding! Reference: How to Load or Save Image using Hibernate – MySQL from our JCG partner Loiane Groner at the Loiane Groner’s blog blog....

Why I will continue to use Spring *and* Java EE in new Enterprise Java Projects in 2012/2013

Over one year passed since my technology decision making post and I am glad to see that I am still in perfect harmony with it. Some months ago I have written an answer to a nice blog of Kai Wähner about JEE vs. Spring. If view points don’t differ then where is the value add in a discussion? I do agree to many of Kai’s points. However, to me it’s not Java EE *or* Spring (like suggested in this recent post) and it’s not a matter of features ’cause in the end features are well sorted in both architectural options (and their corresponding ecosystems). If something is missing somebody out there already wrote a good library and put it open source. It’s also not a question of “heavy weight” or “light weight”. After some years any framework will carry some dead freight due to downwards compatibility requirements. For those reasons this blog won’t be a technical essay about the what’s and why’s of Spring and Java EE. I think – in the first place – the whole issue comes down to the question where you want to place framework libraries that you use as development API to write your business applications: in the server library directories or with the WAR/EAR file in WEB-INF/lib. Figure 2: Simplified development architecture of Spring and Java EE applicationsThe biggest relevant difference in Spring and *pure* Java EE applications is that the development framework API in Spring applications is part of the Java application (WAR or EAR file) deployed to an arbitrary Java runtime. In contrast, pure Java EE applications only consist of business code and the application framework is part of the application server. Hence, the business applications directly work on application server APIs. Beside these pure scenarios a majority of todays Java enterprise applications use a mix of Java EE and Spring APIs. It’s possible to make a Java EE *or* Spring decision in almost any distinct subject matter (Web-Services, IoC-Container, GUI and so forth). There are also pure runtime environments for Java EE and Spring applications: Java EE compliant servers (Redhat JBoss, IBM WebSphere, Oracle WebLogic) and VMWare’s vFabric tc Server. So on a green field one could choose pure Java EE application architecture vs. pure Spring application architecture. However, as explained, the most applications out there run a mix. I haven’t made an acedenic evaluation but I suspect that many applications run on a Java EE or Tomcat server environment with a Spring IoC container. Rather then using *only* Java EE or full blown Spring stack it’s just very common to use a well-balanced combination of mature Java EE and Spring API’s. The strength of Java EE is the open standard established in a documented process by various parties. For this reason building applications for this platform is very popular, although many projects use only a little amount of Java EE API. Another important fact to notice is that every (wise) Java packaged software supplier supports the major Java EE platforms. As a result of all this many larger enterprises host Java EE servers in house anyway. Running Spring applications on Java EE servers is near-by then. This setup may provide benefits for enterprises with many dozens or even hundreds of Java applications in production. 1 – Migrating JEE servers is considerably easier because the applications use less server API *directly*. 2 – For the sake of little migration costs, most of the in-house clients will decide to migrate their business applications to current server versions. 3 – Less server generations in IT landscape, less local development environment generations due to little Java versions in production, simpler ALM solutions – all in all: manageable complexity and more homogeneous landscape. 4 – Fast response to new client requirements: if you need new (Spring) features you’ll only compile a new version of WAR/EAR files and deploy the stuff to an arbitrary Java runtime. 5 – The range of potential target runtime environments will be higher compared to Java EE full stack. Which means you may be “more” plattform independent. 6 – With Spring you can add smaller peaces of functionality to your applications or server environments (avoids: Snowball-effect). 7 – Compared to Java EE, the complete innovation cycle is faster (from the feature request to the usage in production). 8 – Spring enhancements are made according to actual real world client project requirements which ensures their practical applicability. 9 – Application development teams remain responsible for the application development stack and can decide flexibly which API fits the clients needs. It’s difficult to achieve all these benefits in a pure Java EE development stack (some of them address conceptual problems in Java EE). One possible option may be to modularise JEE application server architecture. Modularization as a standard, like in Java SE. It may also be valid to think about the release processes (i.e. JCP). As I said previously, I do believe it’s never been JEE *against* Spring in general ’cause these two options work in harmony together in so many instances. Today it’s still a valid option to use both, Spring and Java EE, like explained in my other blog entry. I believe the vital discussion in the past is more about the programming model for our business applications: CDI vs. Spring IoC and JSF vs. Spring MVC. The debate is also often an emotional one about “like EJB” or not (for historical reasons). Furthermore, it’s a lot about *real* independence of your business applications from the underlying platform (server, operating system, hardware). For example: we use EJB as integration technology but the business applications don’t know about it. The key to platform independence is not using either Java EE or Spring but: making sound decisions which APIs to use *directly* in your business applications programming model. And sometimes it may be better not to use some application-server-lib-directory derived ones. Reference: Why I will continue to use Spring *and* Java EE in new Enterprise Java Projects in 2012/2013 from our JCG partner Niklas....

OutOfMemoryError: Java heap space – Analysis and resolution approach

 java.lang.OutOfMemoryError: Java heap problem is one of the most complex problems you can face when supporting or developing complex Java EE applications.This short article will provide you with a description of this JVM HotSpot OutOfMemoryError error message and how you should attack this problem until its resolution.For a quick help guide on how to determine which type of OutOfMemoryError you are dealing with, please consult the related posts found in this Blog. You will also find tutorials on how to analyze a JVM Heap Dump and identify potential memory leaks.java.lang.OutOfMemoryError: Java heap space – what is it?This error message is typically what you will see your middleware server logs (Weblogic, WAS, JBoss etc.) following a JVM OutOfMemoryError condition:· It is generated from the actual Java HotSpot VM native code · It is triggered as a result of Java Heap (Young Gen / Old Gen spaces) memory allocation failure (due to Java Heap exhaustion)Find below a code snippet from the OpenJDK project source code exposing the JVM HotSpot implementation. The code is showing which condition is triggering the OutOfMemoryError: Java heap space condition.# collectedHeap.inline.hppI strongly recommend that you download the HotSpot VM source code from OpenJDK yourself for your own benefit and future reference. http://openjdk.java.net/groups/hotspot/Ok, so my application Java Heap is exhausted…how can I monitor and track my application Java Heap?The simplest way to properly monitor and track the memory footprint of your Java Heap spaces (Young Gen & Old Gen spaces) is to enable verbose GC from your HotSpot VM. Please simply add the following parameters within your JVM start-up arguments:-verbose:gc –XX:+PrintGCDetails –XX:+PrintGCTimeStamps –Xloggc:<app path>/gc.logYou can then follow my tutorial below in order to understand how to read and analyze your HotSpot Java Heap footprint. http://javaeesupportpatterns.blogspot.com/2011/10/verbosegc-output-tutorial-java-7.htmlOk thanks, now I can see that I have a big Java Heap memory problem…but how can I fix it?There are multiple scenarios which can lead to Java Heap depletion such as:· Java Heap space too small vs. your application traffic & footprint · Java Heap memory leak (OldGen space slowly growing over time…) · Sudden and / or rogue Thread(s) consuming large amount of memory in short amount of time etc.Find below a list of high level steps you can follow in order to further troubleshoot:· If not done already, enabled verbose GC >> -verbose:gc · Analyze the verbose GC output and determine the memory footprint of the Java Heap for each of the Java Heap spaces (YoungGen & OldGen) · Analyze the verbose GC output or use a tool like JConsole to determine if your Java Heap is leaking over time. This can be observed via monitoring of the HotSpot old gen space. · Monitor your middleware Threads and generate JVM Thread Dumps on a regular basis, especially when a sudden increase of Java Heap utilization is observed. Thread Dump analysis will allow you to pinpoint potential long running Thread(s) allocating a lot of objects on your Java Heap in a short amount of time; if any · Add the following parameter within your JVM start-up arguments: -XX:HeapDumpOnOutOfMemoryError This will allow your HotSpot VM to generate a binary Heap Dump (HPROF) format. A binary Heap Dump is a critical data allowing to analyze your application memory footprint and / or source(s) of Java Heap memory leakFrom a resolution perspective, my recommendation to you is to analyze your Java Heap memory footprint using the generated Heap Dump. The binary Heap Dump (HPROF format) can be analyzed using the free Memory Analyzer tool (MAT). This will allow you to understand your java application footprint and / or pinpoint source(s) of possible memory leak. Once you have a clear picture of the situation, you will be able to resolve your problem by increasing your Java Heap capacity (via –Xms & Xmx arguments) or reducing your application memory footprint and / or eliminating the memory leaks from your application code. Please note that memory leaks are often found in middleware server code and JDK as well.I tried everything I could but I am still struggling to pinpoint the source of my OutOfMemoryErrorDon’t worry, simply post a comment / question at the end of this article or email me directly @phcharbonneau@hotmail.com. I currently offer free IT / Java EE consulting. Please provide me with your problem description along you’re your generated data such as a download link to your Heap Dump, Thread Dump data, server logs etc. and I will analyze your problem for you.Reference: OutOfMemoryError: Java heap space – Analysis and resolution approach from our JCG partner Pierre-Hugues Charbonneau at the Java EE Support Patterns & Java Tutorial blog....

Spring & JSF integration: Pagination

When working with large datasets you often need to present data in a paged format. Pagination is an interesting problem because it tends to cut across all layers of your application, from the view tier though application services down to the raw calls to your database.When it comes to fetching paged data there are some pretty good solutions available. If you are using JPA then you are probably familiar with the setFirstResult() and setMaxResult() methods available on javax.persistence.Query. Even better is the Spring Data JPA project that provides org.springframework.data.domain.Pageable and org.springframework.data.domain.Page interfaces for use directly in your repositories.With JSF there are also some well documented methods of displaying and fetching paged data. The exact solution will depend on the component suite that you are using but most of them are based around creating a custom javax.faces.model.DataModel implementation. For example MyFaces have suggestions on their wiki, RichFaces have blogged about the problem and PrimeFaces provide a Lazy Loading DataTable.Recently I have been trying to develop something to ease the burden of the JSF developer and remove the need to create the custom DataModels and the backing beans that expose them. The basic idea is that a JSF component will create a lazy loading DataModel on your behalf using EL expressions to fetch the data as it is need.Here is an example:<s:pagedData var="myDataModel" value="#{userRepository.findByLastName( backingBean.lastName, pageRequest.offset, pageRequest.pageSize)}" pageSize="20" />This will create a myDataModel variable that will fetch 20 rows of data at a time by calling userRepository.findByLastName(). The EL expression will be called several time as the DataModel is scrolled.(I am assuming that you are using EL 2.2, if you an older server such as Tomcat 6 you may need to install an updated el-impl.jar.)Each time the EL expression is called a pageRequest variable is made available. This variable provides access the following context information that may be required when fetching a page of data:pageNumber The page number to displaypageSize The page size requestedoffset The offset (first result)sortColumn The column used to sort datasortAscending If the sort is in ascending or descending orderfilters A map of filters to applyOne problem with the DataModel created in the above example is that the total number of rows is unknown. To get this information we need to provide an additional expression:<s:pagedData value="#{userRepository.findByLastName( backingBean.lastName,pageRequest.offset, pageRequest.pageSize)}" rowCount="#{userRepository.countByLastName(backingBean.lastName)}" />The example above has also dropped the var and pageSize attributes, this will use a default page size of 10 and use a variable name of pagedData.If you have used Spring Data you may have noticed how similar the pageRequest variable is to the org.springframework.data.domain.Pageable interface. In fact, as long as Spring Data is on your classpath, pageRequest can be cast to Pageable. Furthermore the component understands the org.springframework.data.domain.Page object so you no longer need the rowCount expression.Here is an example that calls a spring data repository and presents data using MyFaces Tomahawk components. This example also allows you to sort the data by clicking on a column header:<s:pagedData value="#{userRepository.findByLastName(backingBean.lastName, pageRequest)}" /> <t:dataTable value="#{pagedData}" rows="#{pagedData.pageSize}" sortColumn="#{pagedData.sortColumn}" sortAscending="#{pagedData.sortAscending}" var="user"> <t:column> <f:facet name="header"> <t:commandSortHeader columnName="name"> <h:outputText value="User Name" /> </t:commandSortHeader> </f:facet> <h:outputText value="#{user.name}" /> </t:column> <f:facet name="footer"> <t:dataScroller paginator="true" paginatorMaxPages="9" /> </f:facet> </t:dataTable>One final trick up our sleeves is to ensure that when using PrimeFaces the created DataModel is compatible with org.primefaces.model.LazyDataModel. Here the same example as above but using PrimeFaces components:<s:pagedData value="#{userRepository.findByLastName(backingBean.lastName, pageRequest)}" /> <p:dataTable value="#{pagedData}" rows="#{pagedData.pageSize}" paginator="true" lazy="true" var="user"> <p:column headerText="User Name" sortBy="#{user.name}"> <h:outputText value="#{user.name}" /> </p:column> </p:dataTable>If you want to take a look at any of the code for this it is available on GitHub (look at the org.springframework.springfaces.page.ui and org.springframework.springfaces.model packages). I also have a basic sample application showing page mark-up. As always this code is a moving target so you might encounter some problems running the demos.Reference: Integrating Spring & JavaServer Faces : Pagination from our JCG partner Phillip Webb at the Phil Webb’s Blog blog....

Spring Testing Support with TestNG

TestNG is a test framework which is designed to cover all categories of tests: unit, functional, end-to-end, integration, (etc). It includes a lot of features such as flexible test configuration, support for data-driven testing (with @DataProvider), powerful execution model (no more TestSuite) (etc). Spring testing support covers very useful and important features for unit and integration testing of spring based applications. The org.springframework.test.context.testng package provides support classes for TestNG based test cases. This article shows how to test Spring Service layer components by using Spring and TestNG integration. Also next article will show how to test Spring Data Access layer components by using same integration. Used Technologies : JDK 1.6.0_31 Spring 3.1.1 TestNG 6.4 Maven 3.0.2 STEP 1 : CREATE MAVEN PROJECT A maven project is created as follows. (It can be created by using Maven or IDE Plug-in).STEP 2 : LIBRARIES Spring dependencies are added to Maven’ s pom.xml. <properties> <spring.version>3.1.1.RELEASE</spring.version> </properties><dependencies> <!-- Spring 3 dependencies --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-core</artifactId> <version>${spring.version}</version> </dependency><dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>${spring.version}</version> </dependency><dependency> <groupId>org.springframework</groupId> <artifactId>spring-test</artifactId> <version>${spring.version}</version> </dependency><!-- TestNG dependency --> <dependency> <groupId>org.testng</groupId> <artifactId>testng</artifactId> <version>6.4</version> </dependency><!-- Log4j dependency --> <dependency> <groupId>log4j</groupId> <artifactId>log4j</artifactId> <version>1.2.16</version> </dependency></dependencies>STEP 3 : CREATE USER CLASS A new User Class is created. package com.otv.user;/** * User Bean * * @author onlinetechvision.com * @since 19 May 2012 * @version 1.0.0 * */ public class User {private String id; private String name; private String surname;/** * Gets User Id * * @return String id */ public String getId() { return id; }/** * Sets User Id * * @param String id */ public void setId(String id) { this.id = id; }/** * Gets User Name * * @return String name */ public String getName() { return name; }/** * Sets User Name * * @param String name */ public void setName(String name) { this.name = name; }/** * Gets User Surname * * @return String Surname */ public String getSurname() { return surname; }/** * Sets User Surname * * @param String surname */ public void setSurname(String surname) { this.surname = surname; }@Override public String toString() { StringBuilder strBuilder = new StringBuilder(); strBuilder.append("Id : ").append(getId()); strBuilder.append(", Name : ").append(getName()); strBuilder.append(", Surname : ").append(getSurname()); return strBuilder.toString(); }@Override public int hashCode() { final int prime = 31; int result = 1; result = prime * result + ((id == null) ? 0 : id.hashCode()); result = prime * result + ((name == null) ? 0 : name.hashCode()); result = prime * result + ((surname == null) ? 0 : surname.hashCode()); return result; }@Override public boolean equals(Object obj) { if (this == obj) return true; if (obj == null) return false; if (getClass() != obj.getClass()) return false; User other = (User) obj; if (id == null) { if (other.id != null) return false; } else if (!id.equals(other.id)) return false; if (name == null) { if (other.name != null) return false; } else if (!name.equals(other.name)) return false; if (surname == null) { if (other.surname != null) return false; } else if (!surname.equals(other.surname)) return false; return true; } }STEP 4 : CREATE NonExistentUserException CLASS NonExistentUserException Class is created. package com.otv.common.exceptions;/** * Non Existent User Exception * * @author onlinetechvision.com * @since 19 May 2012 * @version 1.0.0 * */ public class NonExistentUserException extends Exception {private static final long serialVersionUID = 1L;public NonExistentUserException(String message) { super(message); } }STEP 5 : CREATE ICacheService INTERFACE ICacheService Interface representing a cache service interface, is created. package com.otv.cache.service;import java.util.concurrent.ConcurrentHashMap;import com.otv.user.User;/** * Cache Service Interface * * @author onlinetechvision.com * @since 19 May 2012 * @version 1.0.0 * */ public interface ICacheService {/** * Gets User Map * * @return ConcurrentHashMap User Map */ ConcurrentHashMap<String, User> getUserMap();}STEP 6 : CREATE CacheService CLASS CacheService Class is created by implementing ICacheService Interface. It provides access to the remote cache… package com.otv.cache.service;import java.util.concurrent.ConcurrentHashMap;import com.otv.user.User;/** * Cache Service Implementation * * @author onlinetechvision.com * @since 19 May 2012 * @version 1.0.0 * */ public class CacheService implements ICacheService {//User Map is injected... private ConcurrentHashMap<String, User> userMap;/** * Gets User Map * * @return ConcurrentHashMap User Map */ public ConcurrentHashMap<String, User> getUserMap() { return userMap; }/** * Sets User Map * * @param ConcurrentHashMap User Map */ public void setUserMap(ConcurrentHashMap<String, User> userMap) { this.userMap = userMap; }}STEP 7 : CREATE IUserService INTERFACE IUserService Interface representing User Service interface is created. package com.otv.user.service;import java.util.Collection;import com.otv.common.exceptions.NonExistentUserException; import com.otv.user.User;/** * * User Service Interface * * @author onlinetechvision.com * @since 19 May 2012 * @version 1.0.0 * */ public interface IUserService {/** * Adds User * * @param User user * @return boolean whether delete operation is success or not. */ boolean addUser(User user);/** * Deletes User * * @param User user * @return boolean whether delete operation is success or not. */ boolean deleteUser(User user);/** * Updates User * * @param User user * @throws NonExistentUserException */ void updateUser(User user) throws NonExistentUserException;/** * Gets User * * @param String User Id * @return User */ User getUserById(String id);/** * Gets User Collection * * @return List - User list */ Collection<User> getUsers(); }STEP 8 : CREATE UserService CLASS UserService Class is created by implementing IUserService Interface. package com.otv.user.service;import java.util.Collection; import com.otv.cache.service.ICacheService; import com.otv.common.exceptions.NonExistentUserException; import com.otv.user.User;/** * * User Service * * @author onlinetechvision.com * @since 19 May 2012 * @version 1.0.0 * */ public class UserService implements IUserService {//CacheService is injected... private ICacheService cacheService;/** * Adds User * * @param User user * @return boolean whether delete operation is success or not. */ public boolean addUser(User user) {getCacheService().getUserMap().put(user.getId(), user); if(getCacheService().getUserMap().get(user.getId()).equals(user)) { return true; }return false; }/** * Deletes User * * @param User user * @return boolean whether delete operation is success or not. */ public boolean deleteUser(User user) { User removedUser = getCacheService().getUserMap().remove(user.getId()); if(removedUser != null) { return true; } return false; }/** * Updates User * * @param User user * @throws NonExistentUserException */ public void updateUser(User user) throws NonExistentUserException { if(getCacheService().getUserMap().containsKey(user.getId())) { getCacheService().getUserMap().put(user.getId(), user); } else { throw new NonExistentUserException("Non Existent User can not update! User : "+user); } }/** * Gets User * * @param String User Id * @return User */ public User getUserById(String id) { return getCacheService().getUserMap().get(id); }/** * Gets User List * * @return Collection - Collection of Users */ public Collection<User> getUsers() { return (Collection<User>) getCacheService().getUserMap().values(); }/** * Gets Cache Service * * @return ICacheService - Cache Service */ public ICacheService getCacheService() { return cacheService; }/** * Sets Cache Service * * @param ICacheService - Cache Service */ public void setCacheService(ICacheService cacheService) { this.cacheService = cacheService; }}STEP 9 : CREATE UserServiceTester CLASS User Service Tester Class is created by extending AbstractTestNGSpringContextTests. package com.otv.user.service.test;import junit.framework.Assert;import org.apache.log4j.Logger; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.testng.AbstractTestNGSpringContextTests; import org.testng.annotations.AfterClass; import org.testng.annotations.AfterMethod; import org.testng.annotations.AfterTest; import org.testng.annotations.BeforeClass; import org.testng.annotations.BeforeMethod; import org.testng.annotations.BeforeTest; import org.testng.annotations.Test;import com.otv.common.exceptions.NonExistentUserException; import com.otv.user.User; import com.otv.user.service.IUserService;/** * User Service Tester Class * * @author onlinetechvision.com * @since 19 May 2012 * @version 1.0.0 * */ @ContextConfiguration(locations={"classpath:applicationContext.xml"}) public class UserServiceTester extends AbstractTestNGSpringContextTests {private static Logger logger = Logger.getLogger(UserServiceTester.class);@Autowired private IUserService userService;private User firstUser; private User secondUser; private User thirdUser;/** * Creates Test Users * */ private void createUsers() { firstUser = new User(); firstUser.setId("1"); firstUser.setName("Lionel"); firstUser.setSurname("Messi");secondUser = new User(); secondUser.setId("2"); secondUser.setName("David"); secondUser.setSurname("Villa");thirdUser = new User(); thirdUser.setId("3"); thirdUser.setName("Andres"); thirdUser.setSurname("Iniesta"); }/** * Asserts that User Properties are not null. * * @param User */ private void assertNotNullUserProperties(User user) { Assert.assertNotNull("User must not be null!", user); Assert.assertNotNull("Id must not be null!", user.getId()); Assert.assertNotNull("Name must not be null!", user.getName()); Assert.assertNotNull("Surname must not be null!", user.getSurname()); }/** * The annotated method will be run before any test method belonging to the classes * inside the <test> tag is run. * */ @BeforeTest public void beforeTest() { logger.debug("BeforeTest method is run..."); }/** * The annotated method will be run before the first test method in the current class * is invoked. * */ @BeforeClass public void beforeClass() { logger.debug("BeforeClass method is run..."); createUsers(); }/** * The annotated method will be run before each test method. * */ @BeforeMethod public void beforeMethod() { logger.debug("BeforeMethod method is run..."); }/** * Tests the process of adding user * */ @Test public void addUser() { assertNotNullUserProperties(firstUser); Assert.assertTrue("User can not be added! User : " + firstUser, getUserService().addUser(firstUser)); }/** * Tests the process of querying user * */ @Test public void getUserById() { User tempUser = getUserService().getUserById(firstUser.getId()); assertNotNullUserProperties(tempUser); Assert.assertEquals("Id is wrong!", "1", tempUser.getId()); Assert.assertEquals("Name is wrong!", "Lionel", tempUser.getName()); Assert.assertEquals("Surname is wrong!", "Messi", tempUser.getSurname()); }/** * Tests the process of deleting user * */ @Test public void deleteUser() { assertNotNullUserProperties(secondUser); Assert.assertTrue("User can not be added! User : " + secondUser, getUserService().addUser(secondUser)); Assert.assertTrue("User can not be deleted! User : " + secondUser, getUserService().deleteUser(secondUser)); }/** * Tests the process of updating user * @throws NonExistentUserException * */ @Test(expectedExceptions = NonExistentUserException.class) public void updateUser() throws NonExistentUserException { getUserService().updateUser(thirdUser); }/** * Test user count * */ @Test public void getUserCount() { Assert.assertEquals(1, getUserService().getUsers().size()); }/** * The annotated method will be run after all the test methods in the current class have been run. * */ @AfterClass public void afterClass() { logger.debug("AfterClass method is run..."); }/** * The annotated method will be run after all the test methods belonging to the classes inside the <test> tag have run. * */ @AfterTest public void afterTest() { logger.debug("AfterTest method is run..."); }/** * The annotated method will be run after each test method. * */ @AfterMethod public void afterMethod() { logger.debug("AfterMethod method is run..."); }/** * Gets User Service * * @return IUserService User Service */ public IUserService getUserService() { return userService; }/** * Sets User Service * * @param IUserService User Service */ public void setUserService(IUserService userService) { this.userService = userService; }}STEP 10 : CREATE applicationContext.xml Application Context is created as follows : <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans-3.0.xsd"><!-- User Map Declaration --> <bean id="UserMap" class="java.util.concurrent.ConcurrentHashMap" /><!-- Cache Service Declaration --> <bean id="CacheService" class="com.otv.cache.service.CacheService"> <property name="userMap" ref="UserMap"/> </bean><!-- User Service Declaration --> <bean id="UserService" class="com.otv.user.service.UserService"> <property name="cacheService" ref="CacheService"/> </bean> </beans>STEP 11 : RUN PROJECT In this article, TestNG Eclipse Plugin has been used. If you use Eclipse, it can be downloaded via TestNG download page If UserServiceTester is run, results of the test cases are shown as follows :STEP 12 : DOWNLOAD OTV_SpringTestNG REFERENCES : Spring Testing Support TestNG Reference Reference: Spring Testing Support with TestNG from our JCG partner Eren Avsarogullari at the Online Technology Vision blog....

JavaFX 2 GameTutorial Part 3

Introduction This is part 3 of a six part series related to a JavaFX 2 Game Tutorial. If you’ve missed Part 1 and Part 2, I encourage you to go through them before beginning this tutorial. To recap Part 2 I discussed the inner workings of a gaming loop where we used an animation (JavaFX Timeline) to update sprites, check collisions, and clean up game world elements.I then felt compelled to create a simple game engine to enable the ease of developing 2D games. This tutorial is about using the game engine and demonstrating input using your mouse and keyboard.In this tutorial I will give you some background history, event handling fundamentals, a demo game, and finally the implementation. The demo will showcase a spaceship capable of shooting at floating spheres similar to the video game Asteroids. If you want to run the demo,scroll down and click on the WebStart button below. Please read the requirements before launching the game.History Back in the day (during the 80s) as a kid growing up there were arcade centers, bowling alleys, pizza parlors, and 7 Eleven stores where I spent huge amounts of time putting quarters on the glass display areas to be next in line to the guy who was currently playing an intense video game. As everyone was crowded around him watching him beat the all time high score we all cheered as we witnessed greatness. One of those incredibly awesome arcade games was ‘Asteroids‘ created by Atari Inc.(to play visit play.vg) Speaking of high scores, not too many folks know, but Scott Safran (February 3, 1967 – March 27, 1989) had the highest record of all time playing Asteroids. He achieved this at his local 7-Eleven convenience store by playing for approximately twenty hours non stop. Later in life (while still young), he passed away from a tragic accident on March 27, 1989. In Honor of Scott, I created this tutorial. I hope people will remember him as one of the greatest video gamers of all time (I’m sure a good brother and son also). Regarding the game, Asteroids, vector based hardware was used to render shapes as opposed to raster graphics (bitmap). On an added note, Space Invaders by Midway Inc.was created using raster graphics. It’s exciting to point out that there are discussions about JavaFX 2.x having the ability to use bitmaps called the JavaFX Canvas Node which can provide raster graphics to enable developers to take advantage of pixel level manipulations. I am still amazed at the construction of these arcade style cabinets which house the CRT, motherboard, and the controllers (input devices) such as buttons, joystick, track balls, and turning knobs. Classic Arcade Games Below are some classic arcade games with many types of input devices:Buttons only:Asteroids, Space Invaders, Rip Off, Phoenix Joystick only:Q*bert, PacMan Turn knob only:Pong Track ball only:Marble Madness Steering column and buttons:Star Wars, Pole position, Spy Hunter Bike handle bars:Stunt Cycle, Paper Boy Buttons and Throttle bar:Lunar Lander Periscope and Buttons:Sea Wolf Buttons and Yoke:Tron, Battle Zone Buttons, Turn knob, and Yoke: Star Trek, Tempest Buttons and track ball:Missile Command, Centipede Buttons and Joystick:Defender, Gauntlet, Frogger, Joust, Berzerk, Mario Bros., Donkey Kong, Xevious,Galaga, Kung Fu, Contra, Street Fighter, Double Dragon, Ninja magic (or spirit), DigDug,Dragon’s Lair.Input / (Mouse, Keyboard) Leaving the past behind, we currently encounter new kinds of input devices such as touch screens, accelerometers,infrared receivers, cameras, etc. The most common input on the desktop today is the mouse and keyboard. Of course, touch screen is all the rage with mobile devices and tablets, however in this tutorial we will only be focusing on the ‘Mouse‘ and ‘Keyboard‘ as inputs to control your game. Based on the JavaFX Roadmap, multi-touch inputis in the works (by the time you read this it’s already implemented). When intercepting keyboard and mouse events, JavaFX 2.x has many types of events which provide an opportunity for the developer to implement event handlers that intercept the events triggered. The JavaFX 2.x API for the Node or Scene contains many methods having the prefix ‘on’ such as the onMousePressProperty() or onKeyPressProperty()method. Whenever you implement these methods you will simply implement the handle() method using Java’s generic type to specify the event object to be passed in for interrogation. So, when you instantiate an EventHandler<MouseEvent> class you will implement ahandle() method that takes a MouseEvent as a parameter to be passed in. The code snippets shown below add two event handlers to the JavaFX Scene. The first handler will respond to mouse events. In our simple game when a mouse press occurs, this handler will respond by firing the weapon or navigating the ship. The second handler shown below will respond to key event. When a key is pressed, this handler will process KeyEvent objects. In our game, the keystroke ‘2‘ will change your secondary weapon into a bigger blaster (slower). Any other keystroke will default back to the smaller blaster (faster). Move ship and Fire weapon EventHandler fireOrMove = new EventHandler<MouseEvent>() { @Override public void handle(MouseEvent event) { if (event.getButton() == MouseButton.PRIMARY) { // Fire weapon systems. On Windows left mouse button } else if (event.getButton() == MouseButton.SECONDARY) { // Navigate ship thrust. On Windows right mouse button } } }; primaryStage.getScene().setOnMousePressed(fireOrMove);Changing the weapon EventHandler changeWeapons = new EventHandler<KeyEvent>() { @Override public void handle(KeyEvent event) { myShip.changeWeapon(event.getCode()); } }; primaryStage.getScene().setOnKeyPressed(changeWeapons);JavaFX 2 Input Demo – ‘The Expanse’ The simple demo game will be a mix between StarCraft and Asteroids. When using the mouse to navigate the ship it will resemble StarCraft’s Battle Cruiser. If you remember from Part 2 of this series, I created spheres bouncing around. I reused the code from Part 2 ‘Atom Smasher’ to act as asteroids like in the famous arcade game. Except in this game you cannot get harmed at all. The objective is to fire your weapon at the spheres before they hit other spheres which implode upon impact. Because this is a simple tutorial, or even a game in its early stages of development, the game doesn’t keep track of the score. I encourage you to go to GitHub to download the code and enhance the game. Later, you will see a high level UML class diagram describing the classes that make up the game. For the sake of brevity, I will not be going through each class in great detail, but I trust you will visit GitHub here: https://github.com/carldea/JFXGen for all the demos and source code. Requirements:Java 7 or later JavaFX 2.1 or later Windows XP or later (Should be available soon for Linux/MacOS)A simple Asteroid type game called ‘The Expanse’. Instructions:Right mouse click (on Windows) to fly ship. Left mouse click (left click on Windows mouse) to fire weapon. Key press ’2? to change to large missiles.(blue circular projectiles) Other key press defaults to smaller missiles. (red circular projectiles)Part 3 ‘The Expanse’Shown below is figure 2 of a high level class diagram depicting all the classes created for this demo. The GameWorld and Sprite classes are part of the game engine from the previous post. The rest of the classes are new which make up this demo for this tutorial.InputPart3 TheInputPart3is 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 of the main JavaFX application Input Part3. import carlfx.gameengine.GameWorld; package carlfx.demos.navigateship;import javafx.application.Application; import javafx.stage.Stage;/** * The main driver of the game. * @author cdea */ public class InputPart3 extends Application {GameWorld gameWorld = new TheExpanse(59, "JavaFX 2 GameTutorial Part 3 - Input"); /** * @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(); }}TheExpanse The TheExpanse class inherits from the GameWorld class. This is practically identical to Part 2?s ‘AtomSmasher’ where the driver application will invoke the GameWorld instance’s initialize() method to set up all the game elements such as the input, spaceship, and those pesky floating spheres. The job of this class is to make sure asteroids or spheres bounce off walls and remove any missiles which reach the edge of the screen. It’s main responsibly is to manage the assets and create new levels. When there are no moving objects and the player moves the ship on the screen new spheres will be generated for the next level.The key take away from this class is the setupInput() method. The setupInput() method which I created is responsible for establishing your event handlers to be able to listen to key events and mouse event. package carlfx.demos.navigateship;import carlfx.gameengine.GameWorld; import carlfx.gameengine.Sprite; import javafx.event.ActionEvent; import javafx.event.EventHandler; import javafx.scene.CacheHint; import javafx.scene.Group; import javafx.scene.Node; import javafx.scene.Scene; import javafx.scene.control.Button; import javafx.scene.control.Label; import javafx.scene.control.TextField; import javafx.scene.input.KeyEvent; import javafx.scene.input.MouseButton; import javafx.scene.input.MouseEvent; import javafx.scene.layout.HBox; import javafx.scene.layout.VBox; import javafx.scene.paint.Color; import javafx.scene.shape.Circle; import javafx.stage.Stage;import java.util.Random;/** * 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 will navigate his/her ship by right clicking the mouse to * trust forward and left click to fire weapon to atoms. * * @author cdea */ public class TheExpanse extends GameWorld {// mouse pt label Label mousePtLabel = new Label();// mouse press pt label Label mousePressPtLabel = new Label();TextField xCoordinate = new TextField("234"); TextField yCoordinate = new TextField("200"); Button moveShipButton = new Button("Rotate ship");Ship myShip = new Ship();public TheExpanse(int fps, String title) { super(fps, title); }/** * Initialize the game world by adding sprite objects. * * @param primaryStage The game window or primary stage. */ @Override public void initialize(final Stage primaryStage) { // Sets the window title primaryStage.setTitle(getWindowTitle()); //primaryStage.setFullScreen(true);// Create the scene setSceneNodes(new Group()); setGameSurface(new Scene(getSceneNodes(), 800, 600)); getGameSurface().setFill(Color.BLACK); primaryStage.setScene(getGameSurface()); // Setup Game input setupInput(primaryStage);// Create many spheres generateManySpheres(2);// 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(); getSpriteManager().addSprites(myShip); getSceneNodes().getChildren().add(myShip.node);// mouse point VBox stats = new VBox();HBox row1 = new HBox(); mousePtLabel.setTextFill(Color.WHITE); row1.getChildren().add(mousePtLabel); HBox row2 = new HBox(); mousePressPtLabel.setTextFill(Color.WHITE); row2.getChildren().add(mousePressPtLabel);stats.getChildren().add(row1); stats.getChildren().add(row2);// mouse point HBox enterCoord1 = new HBox(); enterCoord1.getChildren().add(xCoordinate); enterCoord1.getChildren().add(yCoordinate); enterCoord1.getChildren().add(moveShipButton); stats.getChildren().add(enterCoord1); moveShipButton.setOnAction(new EventHandler() { @Override public void handle(ActionEvent actionEvent) { double x = Double.parseDouble(xCoordinate.getText()); double y = Double.parseDouble(yCoordinate.getText()); myShip.plotCourse(x, y, false); } });// =================================================== // Debugging purposes // uncomment to test mouse press and rotation angles. //getSceneNodes().getChildren().add(stats); }/** * Sets up the mouse input. * * @param primaryStage The primary stage (app window). */ private void setupInput(Stage primaryStage) { System.out.println("Ship's center is (" + myShip.getCenterX() + ", " + myShip.getCenterY() + ")");EventHandler fireOrMove = new EventHandler() { @Override public void handle(MouseEvent event) { mousePressPtLabel.setText("Mouse Press PT = (" + event.getX() + ", " + event.getY() + ")"); if (event.getButton() == MouseButton.PRIMARY) { // Aim myShip.plotCourse(event.getX(), event.getY(), false); // fire Missile m1 = myShip.fire(); getSpriteManager().addSprites(m1); getSceneNodes().getChildren().add(0, m1.node); } else if (event.getButton() == MouseButton.SECONDARY) { // determine when all atoms are not on the game surface. Ship should be one sprite left. if (getSpriteManager().getAllSprites().size() generateManySpheres(30); }// stop ship from moving forward myShip.applyTheBrakes(event.getX(), event.getY()); // move forward and rotate ship myShip.plotCourse(event.getX(), event.getY(), true); }} };// Initialize input primaryStage.getScene().setOnMousePressed(fireOrMove); //addEventHandler(MouseEvent.MOUSE_PRESSED, me);// set up stats EventHandler changeWeapons = new EventHandler() { @Override public void handle(KeyEvent event) { myShip.changeWeapon(event.getCode()); } }; primaryStage.getScene().setOnKeyPressed(changeWeapons);// set up stats EventHandler showMouseMove = new EventHandler() { @Override public void handle(MouseEvent event) { mousePtLabel.setText("Mouse PT = (" + event.getX() + ", " + event.getY() + ")"); } };primaryStage.getScene().setOnMouseMoved(showMouseMove); }/** * Make some more space spheres (Atomic particles) * * @param numSpheres The number of random sized, color, and velocity atoms to generate. */ private void generateManySpheres(int numSpheres) { Random rnd = new Random(); Scene gameSurface = getGameSurface(); for (int i = 0; i < numSpheres; i++) { Color c = Color.rgb(rnd.nextInt(255), rnd.nextInt(255), rnd.nextInt(255)); Atom b = new Atom(rnd.nextInt(15) + 5, c, true); Circle circle = b.getAsCircle(); // random 0 to 2 + (.0 to 1) * random (1 or -1) b.vX = (rnd.nextInt(2) + rnd.nextDouble()) * (rnd.nextBoolean() ? 1 : -1); b.vY = (rnd.nextInt(2) + rnd.nextDouble()) * (rnd.nextBoolean() ? 1 : -1); // random x between 0 to width of scene double newX = rnd.nextInt((int) gameSurface.getWidth()); // check for the right of the width newX is greater than width // minus radius times 2(width of sprite) if (newX > (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()); circle.setCache(true); circle.setCacheHint(CacheHint.SPEED); circle.setManaged(false); // 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) { // advance object sprite.update(); if (sprite instanceof Missile) { removeMissiles((Missile) sprite); } else { bounceOffWalls(sprite); } }/** * Change the direction of the moving object when it encounters the walls. * * @param sprite The sprite to update based on the wall boundaries. * TODO The ship has got issues. */ private void bounceOffWalls(Sprite sprite) { // bounce off the walls when outside of boundariesNode displayNode; if (sprite instanceof Ship) { displayNode = sprite.node;//((Ship)sprite).getCurrentShipImage(); } else { displayNode = sprite.node; } // Get the group node's X and Y but use the ImageView to obtain the width. if (sprite.node.getTranslateX() > (getGameSurface().getWidth() - displayNode.getBoundsInParent().getWidth()) || displayNode.getTranslateX() < 0) { // bounce the opposite direction sprite.vX = sprite.vX * -1; } // Get the group node's X and Y but use the ImageView to obtain the height. if (sprite.node.getTranslateY() > getGameSurface().getHeight() - displayNode.getBoundsInParent().getHeight() || sprite.node.getTranslateY() < 0) { sprite.vY = sprite.vY * -1; } } /** * Remove missiles when they reach the wall boundaries. * * @param missile The missile to remove based on the wall boundaries. */ private void removeMissiles(Missile missile) { // bounce off the walls when outside of boundaries if (missile.node.getTranslateX() > (getGameSurface().getWidth() - missile.node.getBoundsInParent().getWidth()) || missile.node.getTranslateX() < 0) { getSpriteManager().addSpritesToBeRemoved(missile); getSceneNodes().getChildren().remove(missile.node); } if (missile.node.getTranslateY() > getGameSurface().getHeight() - missile.node.getBoundsInParent().getHeight() || missile.node.getTranslateY() < 0) {getSpriteManager().addSpritesToBeRemoved(missile); getSceneNodes().getChildren().remove(missile.node); } }/** * How to handle the collision of two sprite objects. Stops the particle * by zeroing out the velocity if a collision occurred. * * @param spriteA Sprite from the first list. * @param spriteB Sprite from the second list. * @return boolean returns a true if the two sprites have collided otherwise false. */ @Override protected boolean handleCollision(Sprite spriteA, Sprite spriteB) { if (spriteA != spriteB) { if (spriteA.collide(spriteB)) { if (spriteA instanceof Atom && spriteB instanceof Atom) {((Atom) spriteA).implode(this); // will remove from the Scene onFinish() ((Atom) spriteB).implode(this); getSpriteManager().addSpritesToBeRemoved(spriteA, spriteB);return true; } } }return false; }}Ship The Shipclass represents our cool looking spaceship. The Ship class inherits from the Sprite class to help us contain velocity information (vector). This class will also contain a doubly linked list containing 32 ImageView (RotatedShipImage) instances which represent each direction to simulate the ship rotating about its center (centroid). At some point I want to change this by making a single SVGPath object to be rotated (I know there are trade offs). For this tutorial I implemented the ship by taking ImageViews objects to be rotated 32 direction evenly from 0 to 360 degrees. Shown below in Figure 3 are all 32 directions using 32 ImageView instances and a single Image object of the image of a spaceship to simulate the rotation about its center (pivot point).When animating the ship rotating I simply set all but the current image visible using the setVisible(true) method on the ImageView node. Disclaimer: In gaming you will inevitably encounter math (Trigonometry). If you are interested and want to dig deeper please look at the source code of the TheExpanse class’ initialize() method. At the end of the method uncomment the statement: getSceneNodes().getChildren().add(stats);. This will display controls which will allow you to use to debug and inspect mouse press coordinates. Also, you can see output in your console (stdout) relating to angles, vectors, etc. The Ship’s member variables:turnDirection – enum DIRECTION with Clockwise, CounterClockwise, and Neither u – Vec object which contains a vector in relation to the center of the ship coordinates denoting the starting direction the ship begins to rotate directionalShips – list of RotatedShipImage objects each having a previous and next reference to other RotatedShipImage objects. Zero degrees (uIndex=0) is when the spaceship facing east. When rotating a JavaFX nodes going in a counter clockwise direction is positive numbers in degrees uIndex – index of the current RotatedShipImage in the directionalShips list that is to be displayed vIndex – index of the RotatedShipImage in the directionalShips list that is to be displayed at the end of the rotation animation stopArea – a JavaFX Circle with a radius for the ship to know when to stop the ship from moving flipBook – A JavaFX Group containing all RotatedShipImage objects (32). The group is rendered on the Scene. Like a flip book in animation each RotatedShipImage will be determined to be displayed based on uIndex and vIndex keyCode – a JavaFX KeyCode will help determine if a key press to help change your weapon (character ’2?)The Ship’s member functions:update() – Updates the ships velocity and direction. Also will determine when to stop moving. getCurrentShipImage() – Based on the uIndex it returns the ImageView that is the current ship direction image that is being displayed getCenterX() – returns the screen’s X coordinate of the center of the ship getCenterY() – returns the screen’s X coordinate of the center of the ship plotCourse(double screenX, double screenY, boolean thrust) – After the user clicks their mouse on the screen this method will calculate the angle to rotate the ship and change the velocity to thrust toward the coordinates onto the destination point. When using the Vec object the screen coordinates will be converted to Cartesian coordinates for determining the angle between two vectors (U and V). turnShip() – The plotCourse() method calls turnShip() method to perform the actual animation of the rotation of the ship applyTheBrakes(double screenX, double screenY) – After the user has chosen (right mouse click) where the ship will navigate to applyTheBrakes() method simply sets up the stopArea (Circle) object to let the ship know when to stop fire() – Returns a Missile (Sprite) object for the game engine to put into the scene. Each missile contains the same direction of the ship with a scaled up velocity (increase speed). Should be faster than the ship can fly. changeWeapon(KeyCode keyCode) – After the user (player) hit the key stroke of a ’2? the weapon will change to create a larger missile projectile but slightly slower. Any other key press will be the default weapon that creates small missile projectiles which are faster moving.Shown below is figure 4 of a class diagram displaying the members of the class Ship. Ship Class DiagramShown below is the source code of the Ship class. package carlfx.demos.navigateship;import carlfx.gameengine.Sprite; import javafx.animation.KeyFrame; import javafx.animation.Timeline; import javafx.animation.TimelineBuilder; import javafx.event.ActionEvent; import javafx.event.EventHandler; import javafx.scene.CacheHint; import javafx.scene.Group; import javafx.scene.Node; import javafx.scene.image.Image; import javafx.scene.input.KeyCode; import javafx.scene.paint.Color; import javafx.scene.shape.Circle; import javafx.util.Duration; import java.util.ArrayList; import java.util.List;/** * A space ship with 32 directions * 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 Ship extends Sprite {/** * 360 degree turn */ private final static int TWO_PI_DEGREES = 360;/** * Number of ship frames and directions the ship is pointing nose */ private final static int NUM_DIRECTIONS = 32;/** * The angle of one direction (adjacent directions) (11.25 degrees) */ private final static float UNIT_ANGLE_PER_FRAME = ((float) TWO_PI_DEGREES / NUM_DIRECTIONS);/** * Amount of time it takes the ship to move 180 degrees in milliseconds. */ private final static int MILLIS_TURN_SHIP_180_DEGREES = 300;/** * When the ship turns on each direction one amount of time for one frame or turn of the ship. (18.75 milliseconds) */ private final static float MILLIS_PER_FRAME = (float) MILLIS_TURN_SHIP_180_DEGREES / (NUM_DIRECTIONS / 2);/** * All possible turn directions Clockwise, Counter Clockwise, or Neither when the user clicks mouse around ship */ private enum DIRECTION { CLOCKWISE, COUNTER_CLOCKWISE, NEITHER }/** * Velocity amount used vector when ship moves forward. scale vector of ship. See flipBook translateX and Y. */ private final static float THRUST_AMOUNT = 3.3f;/***/ private final static float MISSILE_THRUST_AMOUNT = 6.3F;/** * Angle in degrees to rotate ship. *//** * Current turning direction. default is NEITHER. Clockwise and Counter Clockwise. */ private DIRECTION turnDirection = DIRECTION.NEITHER;/** * The current starting position of the vector or coordinate where the nose of the ship is pointing towards. */ private Vec u; // current or start vector/** * All ImageViews of all the possible image frames for each direction the ship is pointing. ie: 32 directions. */ private final List directionalShips = new ArrayList<>();/** * The Timeline instance to animate the ship rotating using images. This is an optical illusion similar to page * flipping as each frame is displayed the previous visible attribute is set to false. No rotation is happening. */ private Timeline rotateShipTimeline;/** * The current index into the list of ImageViews representing each direction of the ship. Zero is the ship * pointing to the right or zero degrees. */ private int uIndex = 0;/** * The end index into the list of ImageViews representing each direction of the ship. Zero is the ship * pointing to the right or zero degrees. */ private int vIndex = 0;/** * The spot where the user has right clicked letting the engine check the ship's center is in this area. */ private final Circle stopArea = new Circle();/** * A group contain all of the ship image view nodes. */ private final Group flipBook = new Group();/** * A key code will be used for weapon selection. */ private KeyCode keyCode;public Ship() {// Load one image. Image shipImage = new Image(getClass().getClassLoader().getResource("ship.png").toExternalForm(), true); stopArea.setRadius(40); RotatedShipImage prev = null;// create all the number of directions based on a unit angle. 360 divided by NUM_DIRECTIONS for (int i = 0; i < NUM_DIRECTIONS; i++) { RotatedShipImage imageView = new RotatedShipImage(); imageView.setImage(shipImage); imageView.setRotate(-1 * i * UNIT_ANGLE_PER_FRAME); imageView.setCache(true); imageView.setCacheHint(CacheHint.SPEED); imageView.setManaged(false); imageView.prev = prev; imageView.setVisible(false); directionalShips.add(imageView); if (prev != null) { prev.next = imageView; } prev = imageView; flipBook.getChildren().add(imageView); } RotatedShipImage firstShip = directionalShips.get(0); firstShip.prev = prev; prev.next = firstShip; // set javafx node to an image firstShip.setVisible(true); node = flipBook; flipBook.setTranslateX(200); flipBook.setTranslateY(300);}/** * Change the velocity of the atom particle. */ @Override public void update() { flipBook.setTranslateX(flipBook.getTranslateX() + vX); flipBook.setTranslateY(flipBook.getTranslateY() + vY);if (stopArea.contains(getCenterX(), getCenterY())) { vX = 0; vY = 0; }}private RotatedShipImage getCurrentShipImage() { return directionalShips.get(uIndex); }/** * The center X coordinate of the current visible image. See <code>getCurrentShipImage()</code> method. * * @return The scene or screen X coordinate. */ public double getCenterX() { RotatedShipImage shipImage = getCurrentShipImage(); return node.getTranslateX() + (shipImage.getBoundsInLocal().getWidth() / 2); }/** * The center Y coordinate of the current visible image. See <code>getCurrentShipImage()</code> method. * * @return The scene or screen Y coordinate. */ public double getCenterY() { RotatedShipImage shipImage = getCurrentShipImage(); return node.getTranslateY() + (shipImage.getBoundsInLocal().getHeight() / 2); }/** * Determines the angle between it's starting position and ending position (Similar to a clock's second hand). * When the user is shooting the ship nose will point in the direction of the mouse press using the primary button. * When the user is thrusting to a location on the screen the right click mouse will pass true to the thrust * parameter. * * @param screenX The mouse press' screen x coordinate. * @param screenY The mouse press' screen ycoordinate. * @param thrust Thrust ship forward or not. True move forward otherwise false. */ public void plotCourse(double screenX, double screenY, boolean thrust) { // get center of ship double sx = getCenterX(); double sy = getCenterY();// get user's new turn position based on mouse click Vec v = new Vec(screenX, screenY, sx, sy); if (u == null) { u = new Vec(1, 0); }double atan2RadiansU = Math.atan2(u.y, u.x); double atan2DegreesU = Math.toDegrees(atan2RadiansU);double atan2RadiansV = Math.atan2(v.y, v.x); double atan2DegreesV = Math.toDegrees(atan2RadiansV);double angleBetweenUAndV = atan2DegreesV - atan2DegreesU;// if abs value is greater than 180 move counter clockwise //(or opposite of what is determined) double absAngleBetweenUAndV = Math.abs(angleBetweenUAndV); boolean goOtherWay = false; if (absAngleBetweenUAndV > 180) { if (angleBetweenUAndV < 0) { turnDirection = DIRECTION.COUNTER_CLOCKWISE; goOtherWay = true; } else if (angleBetweenUAndV > 0) { turnDirection = DIRECTION.CLOCKWISE; goOtherWay = true; } else { turnDirection = Ship.DIRECTION.NEITHER; } } else { if (angleBetweenUAndV < 0) { turnDirection = Ship.DIRECTION.CLOCKWISE; } else if (angleBetweenUAndV > 0) { turnDirection = Ship.DIRECTION.COUNTER_CLOCKWISE; } else { turnDirection = Ship.DIRECTION.NEITHER; } }double degreesToMove = absAngleBetweenUAndV; if (goOtherWay) { degreesToMove = TWO_PI_DEGREES - absAngleBetweenUAndV; }//int q = v.quadrant();uIndex = Math.round((float) (atan2DegreesU / UNIT_ANGLE_PER_FRAME)); if (uIndex < 0) { uIndex = NUM_DIRECTIONS + uIndex; } vIndex = Math.round((float) (atan2DegreesV / UNIT_ANGLE_PER_FRAME)); if (vIndex < 0) { vIndex = NUM_DIRECTIONS + vIndex; } String debugMsg = turnDirection + " U [m(" + u.mx + ", " + u.my + ") => c(" + u.x + ", " + u.y + ")] " + " V [m(" + v.mx + ", " + v.my + ") => c(" + v.x + ", " + v.y + ")] " + " start angle: " + atan2DegreesU + " end angle:" + atan2DegreesV + " Angle between: " + degreesToMove + " Start index: " + uIndex + " End index: " + vIndex;System.out.println(debugMsg);if (thrust) { vX = Math.cos(atan2RadiansV) * THRUST_AMOUNT; vY = -Math.sin(atan2RadiansV) * THRUST_AMOUNT; } turnShip();u = v; }private void turnShip() {final Duration oneFrameAmt = Duration.millis(MILLIS_PER_FRAME); RotatedShipImage startImage = directionalShips.get(uIndex); RotatedShipImage endImage = directionalShips.get(vIndex); List frames = new ArrayList<>();RotatedShipImage currImage = startImage;int i = 1; while (true) {final Node displayNode = currImage;KeyFrame oneFrame = new KeyFrame(oneFrameAmt.multiply(i), new EventHandler() {@Override public void handle(javafx.event.ActionEvent event) { // make all ship images invisible for (RotatedShipImage shipImg : directionalShips) { shipImg.setVisible(false); } // make current ship image visible displayNode.setVisible(true);// update the current index //uIndex = directionalShips.indexOf(displayNode); } }); // oneFrameframes.add(oneFrame);if (currImage == endImage) { break; } if (turnDirection == DIRECTION.CLOCKWISE) { currImage = currImage.prev; } if (turnDirection == DIRECTION.COUNTER_CLOCKWISE) { currImage = currImage.next; } i++; }if (rotateShipTimeline != null) { rotateShipTimeline.stop(); rotateShipTimeline.getKeyFrames().clear(); rotateShipTimeline.getKeyFrames().addAll(frames); } else { // sets the game world's game loop (Timeline) rotateShipTimeline = TimelineBuilder.create() .keyFrames(frames) .build();}rotateShipTimeline.playFromStart();}/** * Stops the ship from thrusting forward. * * @param screenX the screen's X coordinate to stop the ship. * @param screenY the screen's Y coordinate to stop the ship. */ public void applyTheBrakes(double screenX, double screenY) { stopArea.setCenterX(screenX); stopArea.setCenterY(screenY); }public Missile fire() { Missile m1;float slowDownAmt = 0; if (KeyCode.DIGIT2 == keyCode) { m1 = new Missile(10, Color.BLUE); slowDownAmt = 2.3f; } else { m1 = new Missile(Color.RED); } // velocity vector of the missile m1.vX = Math.cos(Math.toRadians(uIndex * UNIT_ANGLE_PER_FRAME)) * (MISSILE_THRUST_AMOUNT - slowDownAmt); m1.vY = -Math.sin(Math.toRadians(uIndex * UNIT_ANGLE_PER_FRAME)) * (MISSILE_THRUST_AMOUNT - slowDownAmt);// make the missile launch in the direction of the current direction of the ship nose. based on the // current frame (uIndex) into the list of image view nodes. RotatedShipImage shipImage = directionalShips.get(uIndex);// start to appear in the center of the ship to come out the direction of the nose of the ship. double offsetX = (shipImage.getBoundsInLocal().getWidth() - m1.node.getBoundsInLocal().getWidth()) / 2; double offsetY = (shipImage.getBoundsInLocal().getHeight() - m1.node.getBoundsInLocal().getHeight()) / 2;// initial launch of the missile m1.node.setTranslateX(node.getTranslateX() + offsetX + m1.vX); m1.node.setTranslateY(node.getTranslateY() + offsetY + m1.vY); return m1; }public void changeWeapon(KeyCode keyCode) { this.keyCode = keyCode; }}Vec The Vec class is a simple helper container class to assist in holding a mouse click’s screen coordinates and converting them to Cartesian coordinates based on the center of a sprite, image, or shape. This class is used to help determine the angle between two vectors [Math.atan2(y,x)]. By determining the angle the ship is able to perform the rotation animation of the sprite image. Shown below is the source code of the Vec class. package carlfx.demos.navigateship;/** * This class represents a container class to hold a Vector in space and direction * the ship will move. Assuming the center of the ship is the origin the angles can * be determined by a unit circle via Cartesian coordinates. * When the user clicks on the screen the mouse coordinates or screen coordinates * will be stored into the mx and my instance variables. * The x and y data members are converted to cartesian coordinates before storing. * * I purposefully left out getters and setters. In gaming just keep things minimalistic. * @author cdea */ public class Vec { public double mx; public double my;public double x; public double y;/** * This is a default constructor which will take a Cartesian coordinate. * @param x X coordinate of a point on a Cartesian system. * @param y Y coordinate of a point on a Cartesian system. */ public Vec(float x, float y) { this.x = x; this.y = y; }/** * Constructor will convert mouse click points into Cartesian coordinates based on the sprite's center point as * the origin. * @param mx Mouse press' screen X coordinate. * @param my Mouse press' screen Y coordinate. * @param centerX Screen X coordinate of the center of the ship sprite. * @param centerY Screen Y coordinate of the center of the ship sprite. */ public Vec(double mx, double my, double centerX, double centerY) { this.x = convertX(mx, centerX); this.y = convertY(my, centerY); this.mx = mx; this.my = my; }/** * Returns a Cartesian coordinate system's quadrant from 1 to 4. * * first quadrant - 1 upper right * second quadrant - 2 upper left * third quadrant - 3 lower left * fourth quadrant - 4 lower right * * @return int quadrant number 1 through 4 */ public int quadrant() { int q = 0; if (x > 0 && y > 0) { q =1; } else if (x < 0 && y > 0) { q = 2; } else if (x < 0 && y < 0) { q = 3; } else if (x > 0 && y < 0) { q = 4; } return q; } @Override public String toString(){ return "(" + x + "," + y + ") quadrant=" + quadrant(); } /** * Converts point's X screen coordinate into a Cartesian system. * @param mouseX Converts the mouse X coordinate into Cartesian system based on the ship center X (originX). * @param originX The ship center point's X coordinate. * @return double value of a Cartesian system X coordinate based on the origin X. */ static double convertX(double mouseX, double originX) { return mouseX - originX; }/** * Converts point's Y screen coordinate into a Cartesian system. * @param mouseY Converts the mouse Y coordinate into Cartesian system based on the ship center Y (originY). * @param originY The ship center point's Y coordinate. * @return double value of a Cartesian system Y coordinate based on the origin Y. */ static double convertY(double mouseY, double originY) { return originY - mouseY; }}RotatedShipImage A RotatedShipImage class inherits from a JavaFX’s ImageView class, but also contains references to a previous and a next RotatedShipImage instances making up a doubly linked list. Figure 3 depicts 32 images of the of the “ship.png” rendered in each RotatedShipImage which are all placed in a JavaFX Group node. When the ship appears to rotate, one image is displayed at a time. Shown below is the source code of the RotatedShipImageclass. package carlfx.demos.navigateship;import javafx.scene.image.ImageView;/** * Represents a double link list to assist in the rotation of the ship. * This helps to move clockwise and counter clockwise. */ public class RotatedShipImage extends ImageView { public RotatedShipImage next; public RotatedShipImage prev; }Missile The Missile class inherits from the Atom class. The Missile acts as a marker class to differentiate between spheres (asteroids) and missiles. When missiles are created, they will contain the same direction of the ship (where the ship’s nose is pointing) with a larger velocity. Shown below is the source code of the Missile class.. package carlfx.demos.navigateship;import javafx.scene.paint.Color;/** * A missile projectile without the radial gradient. */ public class Missile extends Atom { public Missile(Color fill) { super(5, fill, false); }public Missile(int radius, Color fill) { super(radius, fill, true); } }Conclusion Input is so vital to any game play that it is often hard to get right. Older game engines will poll during a game loop. When using JavaFX 2.x’s event handling, you implement the type of event to be added to the scene graph or to an individual Node object. Hopefully in the future, we will see more ingenious input devices used in gaming (see Oracle’s Java Technology Evangelist Simon Ritter). Keep your eyes open for Part 4 which deals with collision detection. So, stay tuned and feel free to comment. Useful links: 7-Eleven: http://www.7-eleven.com Playing Asteroids: http://www.play.vg/games/4-Asteroids.html Asteroids: http://en.wikipedia.org/wiki/Asteroids_(video_game) Scott Safran: http://en.wikipedia.org/wiki/Scott_Safran Arcade in Backyard: http://www.themysteryworld.com/2011/02/guy-builds-video-arcade-in-his-back.html StarWars downsized: http://techland.time.com/2012/04/26/man-builds-16-scale-star-wars-arcade-game/ Trigonometry:http://en.wikipedia.org/wiki/Trigonometry JavaFX Node API: http://docs.oracle.com/javafx/2/api/javafx/scene/Node.html JavaFX Scene API: http://docs.oracle.com/javafx/2/api/javafx/scene/Scene.html JavaFX SVGPath API: http://docs.oracle.com/javafx/2/api/javafx/scene/shape/SVGPath.html Multi-Touch and Gestures Support: http://www.oracle.com/technetwork/java/javafx/overview/roadmap-1446331.html Pro JavaFX 2 Apress publishing – pg. 62 chapter 2 section on “Handling Input Events” . http://www.apress.com/9781430268727 Java 7 Recipes Apress publishing- pg. 602 chapter 16 Recipe 16-3 “Animating Shapes Along a Path”. http://www.apress.com/9781430240563 Video Game arcade cabinet: http://en.wikipedia.org/wiki/Video_game_arcade_cabinet Raster Graphics: http://en.wikipedia.org/wiki/Raster_graphics Part 3 source code at the GitHub: https://github.com/carldea/JFXGen/tree/master/demos/navigateship JavaFX Canvas Node: http://mail.openjdk.java.net/pipermail/openjfx-dev/2012-April/001210.html JavaFX- Optimizing Performance for JavaFX Applications:http://www.parleys.com/#st=5&id=2738&sl=0 Oracle’s Java Technology Evangelist Simon  Ritter: https://blogs.oracle.com/javaone/entry/interfacing_with_the_interface_javafx Video Game High School episode 1:http://www.rocketjump.com/?video=vghs-episode-1 Video Game High School episode 2:http://www.rocketjump.com/?video=vghs-episode-2-5 Reference: JavaFX 2 GameTutorial Part 3 from our JCG partner Carl Dea at the Carl’s FX Blog blog....

Book review: ‘Are you smart enough to work at Google?’

You need to toss a coin for a football match. The only coin you have is bent and biased towards one outcome. How do you use the coin and ensure a fair toss? I love a good a puzzle and there are certainty plenty of thought provoking mind benders in this book – most of which I had not heard before. Author William Poundstone (author of ‘ How Would You Move Mount Fuji‘ and ‘ Fortune’s Formula‘) describes various puzzles that are describes various puzzles that are likely to be part of a Google interview process – that company now estimated to be running over one billion search requests per day! Some other aspects of Google are covered, but the subject matter is predominately puzzles – all types of puzzles: fermi questions, deductive logic, numeracy skill, algorithmic questions and some grade A counter intuitive mind boggling teasers!William Poundstone One can’t help asking the question why Google bothers with all of this? Surely, the point of an interview is to see if someone can do a certain type of work and the interview should be a fair attempt to assess a candidate’s suitability. I have had the fortune (some would say misfortune) to be part of world of Software engineering for the last 15 years. I am passionate about it, but I’ll be the first to admit it isn’t just about solving fun puzzles. Following best practises, following agreed processes, keeping up to speed with technology, documenting solutions so others can see what’s going on are all very important things to make a good software engineer. And it’s not always sexy work. Sometimes it requires patience debugging ugly code while sticking to a tight project deadline. Ascertaining how good someone is at all this in an interview setting can be difficult – especially when it’s very easy for a good candidate to freeze from nerves or get an unexpected mental block. It’s very difficult to objectify what makes a good software engineer. Sometimes someone very intelligent can get hung up on abstractions or theoritical patterns and forget they have deadlines or just not be a good team player. Sometimes, there’s just inescapable subjectivity.Joel SpolksySo how do brain teasers help out? Acclaimed tech guru, Joel Spolsky advises to avoid asking them in interviews because they are usually just a case of either the candidate knows it or he doesn’t – and not much else. In my opinion, it can take months to understand someone’s technical strengths and weaknesses. Puzzles can be useful for demostrating how someone approaches problem solving, how they think on their feet and how they communicate ideas. So yes they do serve a purpose. But even if they serve no purpose whatsoever other than a bit of fun, that’s fine for me. I love a good puzzle so I really enjoyed this book and for that reason I’d recommend it to anyone who likes to dabble in some cryptic challenges. References: 1. Are you smart enough to work at Google Reference: Book review: ‘Are you smart enough to work at Google?’ from our JCG partner Alex Staveley at the Dublin’s Tech Blog blog....

Implementing Master Slave / Grid Computing Pattern in Akka

Master Slave pattern is a prime example of fault tolerance and parallel computation. The idea behind the pattern is to partition the work into identical sub tasks which are then delegated to Slaves. These slave node or instances will process the work task and send back the result to the master. The master will then compile the resultsreceivedfrom all the slave nodes.Key here is that the Slave nodes are only aware on how to process the task and not aware of what happens to the output. The Master Slave pattern is analogous to the Grid Computing pattern where a control node distributes the work to other nodes. Idea is to make use of the nodes on the network for their computing power. SETI@Home was one of the earliest pioneers in using this model. I have build a similar example with difference being that worker nodes get started on Remote Nodes, Worker Nodes register with Master(WorkServer) and then subsequently start processing work packets. If there is no worker slave registered with Master(WorkServer), the master waits the workers to register. The workers can register at any time and will start getting work packets from there on.The example demonstrates how an WorkerActor system sends a request for registration. The RegisterRemoteWorker recieves the request and forwards the same to JobController where the RoundRobinRouter is updated for the new worker information. The WorkScheduler sends a periodic request to JobController, who then sends packets to all the registered worker actors. The example does not implement fault tolerance with respect to on how to handle failures when the remote actors die or how to re-process packets that have not been processed. Similarly, there may be cases where the remote worker actors might want to shutdown after processing certain amount of packets, they can then indicate to the master to stop giving them work. I will add fault tolerance soon! Updated: Code base updated to handle worker shutdowns. If the remote actors die or shut down, the JobController detects thefail-oversusing remote actorlistenersand updates the router. The code base for the program is available at the following location – https://github.com/write2munish/Akka-Essentials under the GridPatternExample Reference: Implementing Master Slave / Grid Computing Pattern in Akka from our JCG partner Munish K Gupta at the Akka Essentials blog....

Apache Shiro Part 3 – Cryptography

Besides securing web pages and managing access rights Apache Shiro does also basic cryptography tasks. The framework is able to:encrypt and decrypt data, hash data, generate random numbers.Shiro does not implement any cryptography algorithms. All calculations are delegated to Java Cryptography Extension (JCE) API. The main benefit of using Shiro instead of what is already present in Java is ease of use and secure defaults. Shiro crypto module is written in higher abstraction level and by default implements all known best practices. This is third part of series dedicated to Apache Shiro. First part showed how to secure web application and add log in/log out functionality. Second part showed how to store user accounts in database and give users an option to authenticate themselves via PGP certificates. This post begins with a short Shiro and JCE overview and continues with description of few useful conversion utilities. Following chapters explain random number generation, hashing and how to encrypt and decrypt data. The final chapter shows how to customize a cipher and how to create a new one. Overview Shiro cryptography module resides in org.apache.shiro.crypto package. It does not have manual, but fortunately all crypto classes are Javadoc heavy. Javadoc contains everything that would be written in manual. Shiro relies heavily on java cryptography extension. You do not need to understand JCE to use Shiro. However, you need JCE basics to customize it or add new features to it. If you are not interested in JCE, skip to the next chapter. JCE is a set of highly customizable APIs and their default implementation. It is provider-based. If the default implementation does not have what you need, you can easily install a new provider. Each cipher, cipher option, hash algorithm or any other JCE feature has a name. JCE defines two sets of standard names for algorithms and algorithm modes. Those are available with any JDK. Any provider, for example Bouncy Castle, is free to extend the names sets with new algorithms and options. Names are composed into so-called transformations strings which are used to look up needed objects. For example, Cipher.getInstance('DES/ECB/PKCS5Padding') returns DES cipher in ECB mode with PKCS#5 padding. Returned cipher usually requires further initialization, may not use safe defaults and is not thread safe. Apache Shiro composes transformation strings, configures acquired objects and adds thread safety to them. Most importantly, it has easy to use API and adds higher level best practices that should be implemented anyway. Encoding, Decoding and ByteSource Crypto package encrypts, decrypts and hashes byte arrays ( byte[]). If you need to encrypt or hash s string, you have to convert it to byte array first. Conversely, if you need to store hashed or encrypted value in text file or string database column, you have to convert it to string. Text to Byte Array Static class CodecSupport is able to convert the text to byte array and back. The method byte[] toBytes(String source) converts a string to byte array and the method String toString(byte[] bytes) converts it back. Example Use codec support to convert between text and byte array: @Test public void textToByteArray() { String encodeMe = 'Hello, I'm a text.';byte[] bytes = CodecSupport.toBytes(encodeMe); String decoded = CodecSupport.toString(bytes);assertEquals(encodeMe, decoded); }Encode and Decode Byte Arrays Conversion from byte array to string is called encoding. The reverse process is called decoding. Shiro provides two different algorithms:Base64 implemented in class Base64, Hexadecimal implemented in class Hex.Both classes are static and both have encodeToString and decode utility methods available. Examples Encode a random array into its Hexadecimal representation, decode it and verify the result: @Test public void testStaticHexadecimal() { byte[] encodeMe = {2, 4, 6, 8, 10, 12, 14, 16, 18, 20}; String hexadecimal = Hex.encodeToString(encodeMe); assertEquals('020406080a0c0e101214', hexadecimal); byte[] decoded = Hex.decode(hexadecimal); assertArrayEquals(encodeMe, decoded); } Encode a random array into its Byte64 representation, decode it and verify the result: @Test public void testStaticBase64() { byte[] encodeMe = {2, 4, 6, 8, 10, 12, 14, 16, 18, 20}; String base64 = Base64.encodeToString(encodeMe); assertEquals('AgQGCAoMDhASFA==', base64); byte[] decoded = Base64.decode(base64); assertArrayEquals(encodeMe, decoded); }ByteSource Cryptography package often returns an instance of ByteSource interface instead of byte array. Its implementation SimpleByteSource is a simple wrapper around byte array with additional encoding methods available:String toHex() – returns Hexadecimal byte array representation, String toBase64() – returns Base64 byte array representation, byte[] getBytes() – returns wrapped byte array.Examples The test uses ByteSource to encode an array into its Hexadecimal representation. It then decodes it and verifies the result: @Test public void testByteSourceHexadecimal() { byte[] encodeMe = {2, 4, 6, 8, 10, 12, 14, 16, 18, 20}; ByteSource byteSource = ByteSource.Util.bytes(encodeMe); String hexadecimal = byteSource.toHex(); assertEquals('020406080a0c0e101214', hexadecimal); byte[] decoded = Hex.decode(hexadecimal); assertArrayEquals(encodeMe, decoded); } Use Bytesource to encode an array into its Base64 representation. Decode it and verify the result: @Test public void testByteSourceBase64() { byte[] encodeMe = {2, 4, 6, 8, 10, 12, 14, 16, 18, 20}; ByteSource byteSource = ByteSource.Util.bytes(encodeMe); String base64 = byteSource.toBase64(); assertEquals('AgQGCAoMDhASFA==', base64); byte[] decoded = Base64.decode(base64); assertArrayEquals(encodeMe, decoded); }Random Number Generator Random number generator is composed of RandomNumberGenerator interface and its default implementation SecureRandomNumberGenerator. The interface is fairly simple, it has only two methods:ByteSource nextBytes() – generates a random fixed length byte source, ByteSource nextBytes(int numBytes) – generates a random byte source with specified length.The default implementation implements these two methods and provides some additional configuration:setSeed(byte[] bytes) – custom seed configuration, setDefaultNextBytesSize(int defaultNextBytesSize) – the length of nextBytes() output.The seed is a number (byte array in fact) that initializes random number generator. It allows you to generate ‘predictable random numbers’. Two instances of the same random generator initialized with the same seed always generate the same random numbers sequence. It is useful for debugging, but be very careful with it. If you can, do not specify custom seed for cryptography. Use the default one. Unless you really know what you are doing, the attacker may be able to guess the custom one. That would beat all security purposes of random numbers. Under the hood: SecureRandomNumberGenerator delegates random number generation to JCE SecureRandom implementation. Examples First example creates two random number generators and verifies whether they generate two different things: @Test public void testRandomWithoutSeed() { //create random generators RandomNumberGenerator firstGenerator = new SecureRandomNumberGenerator(); RandomNumberGenerator secondGenerator = new SecureRandomNumberGenerator(); //generate random bytes ByteSource firstRandomBytes = firstGenerator.nextBytes(); ByteSource secondRandomBytes = secondGenerator.nextBytes(); //compare random bytes assertByteSourcesNotSame(firstRandomBytes, secondRandomBytes); } Second example creates two random number generators, initializes them with the same seed and checks whether they generate the same expected 20 bytes long random array: @Test public void testRandomWithSeed() { byte[] seed = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}; //create and initialize first random generator SecureRandomNumberGenerator firstGenerator = new SecureRandomNumberGenerator(); firstGenerator.setSeed(seed); firstGenerator.setDefaultNextBytesSize(20);//create and initialize second random generator SecureRandomNumberGenerator secondGenerator = new SecureRandomNumberGenerator(); secondGenerator.setSeed(seed); secondGenerator.setDefaultNextBytesSize(20);//generate random bytes ByteSource firstRandomBytes = firstGenerator.nextBytes(); ByteSource secondRandomBytes = secondGenerator.nextBytes(); //compare random arrays assertByteSourcesEquals(firstRandomBytes, secondRandomBytes);//following nextBytes are also the same ByteSource firstNext = firstGenerator.nextBytes(); ByteSource secondNext = secondGenerator.nextBytes();//compare random arrays assertByteSourcesEquals(firstRandomBytes, secondRandomBytes);//compare against expected values byte[] expectedRandom = {-116, -31, 67, 27, 13, -26, -38, 96, 122, 31, -67, 73, -52, -4, -22, 26, 18, 22, -124, -24}; assertArrayEquals(expectedRandom, firstNext.getBytes()); }Hashing A hash function takes an arbitrary long data as an input and converts it to a smaller fixed length data. Hash function result is called hash. Hashing is one way operation. It is not possible to convert hash back to original data. The most important thing to remember is: always store passwords hash instead of password itself. Never ever store it directly. Shiro provides two hash related interfaces, both support two concepts necessary for secure password hashing: salting and hash iterations:Hash – represents hash algorithm. Hasher – use this to hash passwords.A salt is a random array concatenated to the password before hashing. It is usually stored together with the password. Without salt, identical passwords would have the same hash. That would make password hacking much easier. Specify a number of hash iterations to slow down the hash operation. The slower the operation, the more difficult it is to crack stored passwords. Use a lot of iterations. Hash Hash interface implementations compute hash functions. Shiro implements six standard hash functions: Md2, Md5, Sha1, Sha256, Sha384 and Sha512. Each hash implementation extends from ByteSource. The constructor takes input data, salt and number of required iterations. Salt and iterations number are optional. ByteSource interface methods return:byte[] getBytes() – hash, String toBase64() – hash in Base64 representation, String toHex() – hash in Hexadecimal representation.Following code computes Md5 hash of ‘Hello Md5′ text with no salt: @Test public void testMd5Hash() { Hash hash = new Md5Hash('Hello Md5'); byte[] expectedHash = {-7, 64, 38, 26, 91, 99, 33, 9, 37, 50, -22, -112, -99, 57, 115, -64}; assertArrayEquals(expectedHash, hash.getBytes()); assertEquals('f940261a5b6321092532ea909d3973c0', hash.toHex()); assertEquals('+UAmGltjIQklMuqQnTlzwA==', hash.toBase64());print(hash, 'Md5 with no salt iterations of 'Hello Md5': '); } Next snippet calculates 10 iterations of Sha256 with salt: @Test public void testIterationsSha256Hash() { byte[] salt = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};Hash hash = new Sha256Hash('Hello Sha256', salt, 10); byte[] expectedHash = {24, 4, -97, -61, 70, 28, -29, 85, 110, 0, -107, -8, -12, -93, -121, 99, -5, 23, 60, 46, -23, 92, 67, -51, 65, 95, 84, 87, 49, -35, -78, -115}; String expectedHex = '18049fc3461ce3556e0095f8f4a38763fb173c2ee95c43cd415f545731ddb28d'; String expectedBase64 = 'GASfw0Yc41VuAJX49KOHY/sXPC7pXEPNQV9UVzHdso0='; assertArrayEquals(expectedHash, hash.getBytes()); assertEquals(expectedHex, hash.toHex()); assertEquals(expectedBase64, hash.toBase64());print(hash, 'Sha256 with salt and 10 iterations of 'Hello Sha256': '); } Compare iterations calculated by the framework and by the client code: @Test public void testIterationsDemo() { byte[] salt = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}; //iterations computed by the framework Hash shiroIteratedHash = new Sha256Hash('Hello Sha256', salt, 10);//iterations computed by the client code Hash clientIteratedHash = new Sha256Hash('Hello Sha256', salt); for (int i = 1; i < 10; i++) { clientIteratedHash = new Sha256Hash(clientIteratedHash.getBytes()); } //compare results assertByteSourcesEquals(shiroIteratedHash, clientIteratedHash); } Under the hood: all concrete hash classes extend from SimpleHash which delegates hash computation to JCE MessageDigest implementation. If you wish to extend Shiro with another hash function, instance it directly. The constructor takes JCE message digest (hash) algorithm name as a parameter. Hasher Hasher works on top of hash functions and implements best practices related to salting. The interface has only one method:HashResponse computeHash(HashRequest request)Hash request provides byte source to be hashed and an optional salt. Hash response returns a hash and a salt. The response salt is not necessary the same as supplied salt. More importantly, it may not be the whole salt used for hashing operation. Any hasher implementation is free to generate its own random salt. The default implementation does that only if the request contains null salt. Additionally, used salt may be composed of ‘base salt’ and ‘public salt’. ‘Public salt’ is returned in the hash response. To understand why it is done this way, you have to recall that salt is usually stored together with the password. The attacker with access to the database would have all information needed for brute-force attack. Therefore, the ‘public salt’ is stored at the same place as the password and ‘base salt’ is stored elsewhere. The attacker then needs to get access to two different places. Default hasher is configurable. You can specify base salt, number of iterations and hash algorithm to be used. Use hash algorithm name from any Shiro hash implementation. It also always returns public salt from the hash request. See the demo: @Test public void fullyConfiguredHasher() { ByteSource originalPassword = ByteSource.Util.bytes('Secret');byte[] baseSalt = {1, 1, 1, 2, 2, 2, 3, 3, 3}; int iterations = 10; DefaultHasher hasher = new DefaultHasher(); hasher.setBaseSalt(baseSalt); hasher.setHashIterations(iterations); hasher.setHashAlgorithmName(Sha256Hash.ALGORITHM_NAME); //custom public salt byte[] publicSalt = {1, 3, 5, 7, 9}; ByteSource salt = ByteSource.Util.bytes(publicSalt); //use hasher to compute password hash HashRequest request = new SimpleHashRequest(originalPassword, salt); HashResponse response = hasher.computeHash(request); byte[] expectedHash = {55, 9, -41, -9, 82, -24, 101, 54, 116, 16, 2, 68, -89, 56, -41, 107, -33, -66, -23, 43, 63, -61, 6, 115, 74, 96, 10, -56, -38, -83, -17, 57}; assertArrayEquals(expectedHash, response.getHash().getBytes()); } If you need compare passwords or data check-sums, provide a ‘public salt’ back to the same hasher. It will reproduce the hash operation. The example uses Shiro DefaultHasher implementation: @Test public void hasherDemo() { ByteSource originalPassword = ByteSource.Util.bytes('Secret'); ByteSource suppliedPassword = originalPassword; Hasher hasher = new DefaultHasher(); //use hasher to compute password hash HashRequest originalRequest = new SimpleHashRequest(originalPassword); HashResponse originalResponse = hasher.computeHash(originalRequest); //Use salt from originalResponse to compare stored password with user supplied password. We assume that user supplied correct password. HashRequest suppliedRequest = new SimpleHashRequest(suppliedPassword, originalResponse.getSalt()); HashResponse suppliedResponse = hasher.computeHash(suppliedRequest); assertEquals(originalResponse.getHash(), suppliedResponse.getHash()); //important: the same request hashed twice may lead to different results HashResponse anotherResponse = hasher.computeHash(originalRequest); assertNotSame(originalResponse.getHash(), anotherResponse.getHash()); } Note: as the supplied public salt in the above example was null, default hasher generated new random public salt. Encryption / Decryption A cipher encrypts the data into ciphertext unreadable without a secret key. Ciphers are divided into two groups: symmetric and asymmetric. A symmetric cipher uses the same key for encryption and decryption. Asymmetric cipher uses two different keys, one is used for encryption and another for decryption. Apache Shiro contains two symmetric ciphers: AES and Blowfish. Both are stateless and thus thread-safe. Asymmetric ciphers are not supported. Both ciphers are able to generate random encryption key and both implement CipherService interface. The interface defines two encryption and two decryption methods. First group serves for encryption/decryption of byte arrays:ByteSource encrypt(byte[] raw, byte[] encryptionKey), ByteSource decrypt(byte[] encrypted, byte[] decryptionKey).Second group encrypts/decrypts streams:encrypt(InputStream in, OutputStream out, byte[] encryptionKey), decrypt(InputStream in, OutputStream out, byte[] decryptionKey).Next code snippet generates new key, encrypts secret message with AES cipher, decrypts it and compares original message with decryption result: @Test public void encryptStringMessage() { String secret = 'Tell nobody!'; AesCipherService cipher = new AesCipherService(); //generate key with default 128 bits size Key key = cipher.generateNewKey(); byte[] keyBytes = key.getEncoded(); //encrypt the secret byte[] secretBytes = CodecSupport.toBytes(secret); ByteSource encrypted = cipher.encrypt(secretBytes, keyBytes); //decrypt the secret byte[] encryptedBytes = encrypted.getBytes(); ByteSource decrypted = cipher.decrypt(encryptedBytes, keyBytes); String secret2 = CodecSupport.toString(decrypted.getBytes()); //verify correctness assertEquals(secret, secret2); } Another snipped shows how to encrypt/decryption streams with Blowfish. Shiro ciphers do not close nor flush neither input nor output stream. You have to do it by yourself: @Test public void encryptStream() { InputStream secret = openSecretInputStream(); BlowfishCipherService cipher = new BlowfishCipherService();// generate key with default 128 bits size Key key = cipher.generateNewKey(); byte[] keyBytes = key.getEncoded();// encrypt the secret OutputStream encrypted = openSecretOutputStream(); try { cipher.encrypt(secret, encrypted, keyBytes); } finally { // The cipher does not flush neither close streams. closeStreams(secret, encrypted); }// decrypt the secret InputStream encryptedInput = convertToInputStream(encrypted); OutputStream decrypted = openSecretOutputStream(); try { cipher.decrypt(encryptedInput, decrypted, keyBytes); } finally { // The cipher does not flush neither close streams. closeStreams(secret, encrypted); }// verify correctness assertStreamsEquals(secret, decrypted); } If you encrypt the same text with the same key twice, you will get two different encrypted texts: @Test public void unpredictableEncryptionProof() { String secret = 'Tell nobody!'; AesCipherService cipher = new AesCipherService();// generate key with default 128 bits size Key key = cipher.generateNewKey(); byte[] keyBytes = key.getEncoded();// encrypt two times byte[] secretBytes = CodecSupport.toBytes(secret); ByteSource encrypted1 = cipher.encrypt(secretBytes, keyBytes); ByteSource encrypted2 = cipher.encrypt(secretBytes, keyBytes);// verify correctness assertArrayNotSame(encrypted1.getBytes(), encrypted2.getBytes()); } Both previous examples used Key generateNewKey() method to generate keys. Use the method setKeySize(int keySize) to override the default key size (128 bits). Alternatively, the keyBitSize parameter of the method Key generateNewKey(int keyBitSize) specifies a key size in bits. Some ciphers support only some key sizes. For example, AES supports only 128, 192, and 256 bits log keys: @Test(expected=RuntimeException.class) public void aesWrongKeySize() { AesCipherService cipher = new AesCipherService(); //The call throws an exception. Aes supports only keys of 128, 192, and 256 bits. cipher.generateNewKey(200); }@Test public void aesGoodKeySize() { AesCipherService cipher = new AesCipherService(); //aes supports only keys of 128, 192, and 256 bits cipher.generateNewKey(128); cipher.generateNewKey(192); cipher.generateNewKey(256); } As far as basics go, this is it. You do not need more to encrypt and decrypt sensitive data in your applications. Update: I was overly optimistic here. Learning more is always useful, especially if you are handling sensitive data. This method is mostly, but not entirely secure. Both the problem and the solution are described in my other post. Encryption / Decryption – Advanced Previous chapter showed how to encrypt and decrypt some data. This chapter shows little bit more about how Shiro encryption works and how to customize it. It also shows how to easily add a new cipher if the standard two are not suitable for you. Initialization Vector Initialization vector is randomly generated byte array used during ecryption. The cipher that uses initialization vector is less predictable and thus harder to decrypt for an attacker. Shiro automatically generates initialization vector and uses it to encrypt the data. The vector is then concatenated with encrypted data and returned to client code. You can turn it off by calling setGenerateInitializationVectors(false) on the cipher. The method is defined on JcaCipherService class. Both default encryption classes extend it. Initialization vector size is encryption algorithm specific. If the default size (128 bits) does not work, use the method setInitializationVectorSize to customize it. Random Generator Turning off an initialization vector does not necessary mean that the cipher becomes predictable. Both Blowfish and AES have an element of randomness in them. Following example turns off the initialization vector, but encrypted texts are still different: @Test public void unpredictableEncryptionNoIVProof() { String secret = 'Tell nobody!'; AesCipherService cipher = new AesCipherService(); cipher.setGenerateInitializationVectors(false);// generate key with default 128 bits size Key key = cipher.generateNewKey(); byte[] keyBytes = key.getEncoded();// encrypt two times byte[] secretBytes = CodecSupport.toBytes(secret); ByteSource encrypted1 = cipher.encrypt(secretBytes, keyBytes); ByteSource encrypted2 = cipher.encrypt(secretBytes, keyBytes);// verify correctness assertArrayNotSame(encrypted1.getBytes(), encrypted2.getBytes()); } It is possible to customize or turn off the randomness. However, never ever do it in a production code. The randomness is absolute necessity for secure data encryption. Both Shiro encryption algorithms extend from JcaCipherService class. The class have setSecureRandom(SecureRandom secureRandom) method. Secure random is standard java JCE random number generator. Extend it to create own implementation and pass it to the cipher. Our ConstantSecureRandom implementation of SecureRandom always returns zero. We supplied it to the cipher and turned off the initialization vector to create an unsecure predictable encryption: @Test public void predictableEncryption() { String secret = 'Tell nobody!'; AesCipherService cipher = new AesCipherService(); cipher.setSecureRandom(new ConstantSecureRandom()); cipher.setGenerateInitializationVectors(false);// define the key byte[] keyBytes = {5, -112, 36, 113, 80, -3, -114, 77, 38, 127, -1, -75, 65, -102, -13, -47};// encrypt first time byte[] secretBytes = CodecSupport.toBytes(secret); ByteSource encrypted = cipher.encrypt(secretBytes, keyBytes);// verify correctness, the result is always the same byte[] expectedBytes = {76, 69, -49, -110, -121, 97, -125, -111, -11, -61, 61, 11, -40, 26, -68, -58}; assertArrayEquals(expectedBytes, encrypted.getBytes()); } Constant secure random implementation is long and uninteresting. It is available on Github. Custom Cipher Out of the box Shiro provides only Blowfish and AES encryption methods. The framework does not implement its own algorithms. Instead, it delegates the encryption to JCE classes. Shiro provides only secure defaults and easier API. This design makes it possible to extend Shiro with any JCE block cipher. Block ciphers encrypt messages per blocks. All blocks have equal fixed size. If the last block is too short, a padding is added to make it the same size as all other blocks. Each block is encrypted and combined with previously encrypted blocks. Therefore, you have to configure:encryption method, block size, padding, how to combine blocks.Encryption Method A custom cipher extends a DefaultBlockCipherService class. The class has only one constructor with one parameter: algorithm name. You may supply any JCE compatible algorithm name. For example, this is source code of Shiro AES cipher: public class AesCipherService extends DefaultBlockCipherService {private static final String ALGORITHM_NAME = 'AES';public AesCipherService() { super(ALGORITHM_NAME); }} AES does not need to specify no other encryption parameter (block size, padding, encryption method). Defaults are good enough for AES. Block Size Default block cipher service has two methods for block size customization. The method setBlockSize(int blockSize) works only for byte array encoding and decoding. The method setStreamingBlockSize(int streamingBlockSize) works only for stream encoding and decoding. The value 0 means that the default algorithm specific block size will be used. This is the default value. Block cipher block size is very algorithm-specific. Selected encryption algorithm may not work with an arbitrary block size: @Test(expected=CryptoException.class) public void aesWrongBlockSize() { String secret = 'Tell nobody!'; AesCipherService cipher = new AesCipherService(); // set wrong block size cipher.setBlockSize(200);// generate key with default 128 bits size Key key = cipher.generateNewKey(); byte[] keyBytes = key.getEncoded();// encrypt the secret byte[] secretBytes = CodecSupport.toBytes(secret); cipher.encrypt(secretBytes, keyBytes); }Padding Use the method setPaddingScheme(PaddingScheme paddingScheme) to specify byte array encryption and decryption padding. The method setStreamingPaddingScheme( PaddingScheme paddingScheme) specifies stream encryption and decryption padding. The enumeration PaddingScheme represents all typical padding schemes. Not all of them are available by default, you might have to install custom JCE provider to use them. The value null means that the default algorithm specific padding will be used. This is the default value. If you need a padding not included in the PaddingScheme enumeration, use either setPaddingSchemeName or setStreamingPaddingSchemeName methods. These methods take a string with padding scheme name as a parameter. They are less type-safe but more flexible than the above ones. Padding is very algorithm-specific. Selected encryption algorithm may not work with an arbitrary padding: @Test(expected=CryptoException.class) public void aesWrongPadding() { String secret = 'Tell nobody!'; BlowfishCipherService cipher = new BlowfishCipherService(); // set wrong block size cipher.setPaddingScheme(PaddingScheme.PKCS1);// generate key with default 128 bits size Key key = cipher.generateNewKey(); byte[] keyBytes = key.getEncoded();// encrypt the secret byte[] secretBytes = CodecSupport.toBytes(secret); cipher.encrypt(secretBytes, keyBytes); }Operation Mode Operation mode specifies how are blocks chained (combined) together. As it was with a padding scheme, you might use either an OperationMode enumeration or a string to supply them. Be careful, not each operation mode might be available. Additionally, they are not born equal. Some chaining modes are less safe than others. The default Cipher Feedback operation mode is both safe and available on all JDK environments. Methods to set the operation mode for byte array encryption and decryption:setMode(OperationMode mode) setModeName(String modeName)Methods to set the operation mode for stream encryption and decryption:setStreamingMode(OperationMode mode) setStreamingModeName(String modeName)Exercise – Decrypt Openssl Suppose that an application sends data encrypted with Linux openssl command. We know both hexadecimal representation of the key and command used to encrypt the data:The key: B9FAB84B65870109A6E8707BC95151C245BF18204C028A6A. The command: openssl des3 -base64 -p -K <secret key> -iv <initialization vector>.Each message contains both hexadecimal representation of the initialization vector and base64 encoded encrypted message. Sample message:The initialization vector: F758CEEB7CA7E188. The message: GmfvxhbYJbVFT8Ad1Xc+Gh38OBmhzXOV.Generate Sample With OpenSSL The sample message was encrypted with the command: #encrypt 'yeahh, that worked!' echo yeahh, that worked! | openssl des3 -base64 -p -K B9FAB84B65870109A6E8707BC95151C245BF18204C028A6A -iv F758CEEB7CA7E188 Use OpenSSL option -P to generate either a secret key or a random initial vector. Solution First, we have to find out algorithm name, padding and operation mode. Fortunately, all three are available in OpenSSL documentation. Des3 is an alias for triple DES encryption algorithm in CBC mode and OpenSSL uses PKCS#5 padding. Cipher-block chaining (CBC) requires an initialization vector of the same size as the block size. Triple DES requires 64 bit long blocks. Java JCE uses ‘DESede’ algorithm name for Triple DES. Our custom cipher extends and configures DefaultBlockCipherService: public class OpensslDes3CipherService extends DefaultBlockCipherService {public OpensslDes3CipherService() { super('DESede'); setMode(OperationMode.CBC); setPaddingScheme(PaddingScheme.PKCS5); setInitializationVectorSize(64); } } Shiro cipher decrypt method expects two input byte arrays, ciphertext and key. Ciphertext should contain both initialization vector and encrypted cipher text. Therefore, we have to combine them together before we try to decrypt the message. The method combine combines two arrays into one: private byte[] combine(byte[] iniVector, byte[] ciphertext) { byte[] ivCiphertext = new byte[iniVector.length + ciphertext.length];System.arraycopy(iniVector, 0, ivCiphertext, 0, iniVector.length); System.arraycopy(ciphertext, 0, ivCiphertext, iniVector.length, ciphertext.length);return ivCiphertext; } The actual decryption looks as usually: @Test public void opensslDes3Decryption() { String hexInitializationVector = 'F758CEEB7CA7E188'; String base64Ciphertext = 'GmfvxhbYJbVFT8Ad1Xc+Gh38OBmhzXOV'; String hexSecretKey = 'B9FAB84B65870109A6E8707BC95151C245BF18204C028A6A';//decode secret message and initialization vector byte[] iniVector = Hex.decode(hexInitializationVector); byte[] ciphertext = Base64.decode(base64Ciphertext);//combine initialization vector and ciphertext together byte[] ivCiphertext = combine(iniVector, ciphertext); //decode secret key byte[] keyBytes = Hex.decode(hexSecretKey);//initialize cipher and decrypt the message OpensslDes3CipherService cipher = new OpensslDes3CipherService(); ByteSource decrypted = cipher.decrypt(ivCiphertext, keyBytes); //verify result String theMessage = CodecSupport.toString(decrypted.getBytes()); assertEquals('yeahh, that worked!\n', theMessage); }End This part of Apache Shiro tutorial covered cryptography features available in 1.2 version. All used examples are available on Github. Reference: Apache Shiro Part 3 – Cryptography from our JCG partner Maria Jurcovicova at the This is Stuff blog....
Java Code Geeks and all content copyright © 2010-2014, 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: