Check out our Angular Book Series.

The Learn With Series now includes Java and PHP

The Learn With series now includes a few new book that talk about integrating with Java or PHP.

Check them out now.

I'm greatly enjoying writing these books, experimenting with different technologies, and taking you all along for the ride.

Setting up Java and Jersey with IntelliJ

I put this video together about setting up Java and Jersey using IntelliJ. This demonstrates the project structure I used when writing the Learn With books on Java.

What is the difference between Boolean class and boolean primitive type in Java?

I was recently working on the Java code for the LearnWith series. The application behind the book is a Task Manager application and one of the features is the ability to filter tasks based on their completed state. The database field is a bit field, because a task can either be completed or not completed.

However, from a filtering perspective I need to accommodate for three different states: Completed, not Completed, and All Tasks. How do I handle that in Java?

A database bit column usually turns into a Boolean value in a programming language, and for that it works great. With Java the boolean primitive type is perfect for this. It can support values of true or false. However, boolean does not have an undefined or null state. It must always have a value.

To handle the UI filtering I had to use an instance of the Boolean class. Since it is a class it can be undefined or null. The final code was something like this:


if(BooleanVariable != null){
// do something to handle value
} else {
// do something to handle the null value
}

This stuff should be old hat if you have a lot of Java experience, but from someone who focuses on UI code over server side code, it made me pause for 10 seconds to figure it out.

Why can't IntelliJ find java.time with JDK 9?

I've been working on a a few projects that use the JDK 9 with IntelliJ. My latest started getting an error like this:


java package java.time does not exists
java cannot find symbol
symbol: class LocalDate

The LocalDate class was added to the JDK 8, so this error makes sense if you are building using an earlier version of JDK. But, I should not be seeing it when using JDK 9.

Googling on similar errors seems to bring me back to the same thing I already knew. You're using the wrong version of the JDK, be sure to upgrade to JDK 8 or later.

But, I am already using JDK 9, so should not be having this problem.

I spent an hour pouring over IntelliJ settings before stumbling onto this screen:

The Java Compiler target bytecode version of my project was set to 1.7 instead of 9. I already fixed that in the screenshot above. It made my errors go away immediately.

The most confusing thing is that I didn't have errors on any of the other projects.

How do I copy files with Maven?

Last week, I wrote about running a Gulp Script from Maven. The Gulp Script was located in a directory outside of the Java project.

This week I'll show you how to copy the file from the external directory into the Java project.

We're going to use the maven-resources-plugin to make this work.

First, set it up as a plugin in the Maven POM file:


<plugin>
<artifactId>maven-resources-plugin</artifactId>
<version>3.0.2</version>

This adds the artifactId--AKA the plugin name--and the version number. For each set of files we want to copy, we'll need to add an execution block, so start there:


<executions>
<execution>
<id>copy-resources-A5</id>
<phase>validate</phase>
<goals>
<goal>copy-resources</goal>
</goals>

This specifies the id of the copy, which is just a unique name for the process. It is done on the validation phase. And the goal is to copy-resources.

Before we end the execution block, we need to add the configuration. this will tell us what we are copying and where we are copying it too.


<configuration>
<outputDirectory>${basedir}/src/main/webapp/A5</outputDirectory>
<resources>
<resource>
<directory>C:/Projects/lw/A5/chapter7/Angular5TypeScript/build</directory>
<filtering>true</filtering>
</resource>
</resources>
</configuration>

The outputDirectory specifies the location of the copied files. I made them relative tot he $(basedir), which is the root of the Java project. In the Angular 5 files in the A5 directory of the Java Project's webapp.

The source directory is listed under resources, resource.

Finally close off the open tags, which is the execution tag, the executions tag, and the plugin tag:


</execution>
</executions>
</plugin>

I'm using this approach to copy the results of an external Gulp script into the final WAR, so that the files will be surfable via the Tomcat instance.

It has been working great for me.

How do I run a Gulp Script in a different directory from Maven?

If you want to run a Gulp Script from Maven, you use the frontend plugin, right? Unfortunately, that seems to assume that the Gulp script is part of the Java project.

I'm creating a Java Backend to the LearnWith series and am sharing UI code between multiple backend technologies. As such, my directory structure is different and the UI code is not in the web root. I want to run a gulp script in a different directory, and then copy the results into the project's webapp directory. How do you do it?

I was able to do it with the exec Maven Plugin.

First, set up the plugin in the plugins portion of Maven POM:


<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<version>1.6.0</version>

The groupId, arftifactId, and version are specified. For each script you want to run you'll need an execution statement:


<executions>
<execution>
<id>Build Angular 5</id>
<phase>validate</phase>
<goals>
<goal>exec</goal>
</goals>
<configuration>
<executable>gulp</executable>
<arguments>
<argument>build</argument>
</arguments>
<workingDirectory>C:\Projects\lw\A5\chapter7\Angular5TypeScript</workingDirectory>
</configuration>
</execution>
</executions>

The id is a unique name for the build script. The phase is validate, because it is. The goal should be set to exec. The configuration is where the real magic happens. We tell it to execute the gulp command with the argument 'build', so this will run:


gulp build

We want to make sure that the script runs in the proper directory and that is specified with the workingDirectory tag. Presumably this directory will be outside the current directory structure.

Finally, close the plugin tag:


</plugin>

That's all you need to do to run an external Gulp Script from a Maven project. This assumes, of course, you have Gulp installed. Next week I'm going to write about copying the processed files into the Java project.

How do you get the ID of the inserted row with Java and SQL Server?

I've been playing around with the Learn With series and building the backend services in Java. I was going right along until I got to the chapter to create and update data. The query is something like this:


String SQL = "insert into tasks(taskCategoryID, userID, description, completed, dateCreated) values(?,?, ?, 0, ? )
SELECT SCOPE_IDENTITY() as taskID";

This is a super common approach to creating a new item in SQL Server, and then immediately selecting the newly created ID with SCOPE_IDENTITY(). I'd expect it to work easily.

The rest of the code:


PreparedStatement pstmt = connection.prepareStatement(SQL);

// set parameters
pstmt.setInt(1, taskCategoryID);
pstmt.setInt(2, userID);
pstmt.setString(3, description);
LocalDate dateCreated = LocalDate.now();
pstmt.setObject(4, dateCreated);
ResultSet rs = pstmt.executeQuery();

The last line will throw an error claiming that the query returned no results sets and blow up. I had been swimming along smoothly until I ran into that issue. It turns out that, for updates and inserts, that is the wrong approach. Instead of using executeQuery(), I need to use executeUpdate(), like this:


pstmt.executeUpdate();

After that, I can get the second result set using this:


ResultSet rs = pstmt.getGeneratedKeys();

Then things are good to go.

You'll probably find the LearnWith series supporting Java next month.

How do I copy Multiple Directories with Maven?

I've been playing around with Java since a lot of my clients use it as their service layer to power their Angular applications. As such I'm digging into Maven a common build tool for Java applications.

Java development is more complicated than something like PHP or ColdFusion. With PHP or ColdFusion I can just write a file, throw it in a web directory and load it. Java requires a compilation process, which complicates things a bit. Since I'm building a service layer as part of the Learn With applications, I wanted to copy specific files into my final WAR file. I wanted to copy the front end from the books into the final WAR file, without having to replicate all the UI code in the Java project.

The Maven ">Resource plugin lets me copy files from outside the Java project into the Java project before building the project. Something like this works:


<plugin>
<artifactId>maven-resources-plugin</artifactId>
<version>3.0.2</version>
<executions>
<execution>
<id>copy-resources</id>
<!-- here the phase you need -->
<phase>validate</phase>
<goals>
<goal>copy-resources</goal>
</goals>
<configuration>
<outputDirectory>${basedir}/src/main/webapp/your-dir-here</outputDirectory>
<resources>
<resource>
<directory>C:/non-packaged-resources</directory>
<filtering>true</filtering>
</resource>
</resources>
</configuration>
</execution>
</executions>
</plugin>

This works great to copy non-project files from the resource directory:


<resource>
<directory>C:/non-packaged-resources</directory>
<filtering>true</filtering>
</resource>

This will be external to the project. Into the outputDirectory


<outputDirectory>${basedir}/src/main/webapp/your-dir-here</outputDirectory>

Which is part of the project. Once the files are in the web-app directory they will be compiled into the final WAR file and accessible when that WAR is deployed to a Java server, such as Tomcat.

However, I'm dealing with multiple UI technologies and wanted to copy over all the files. How do I do it? The answer is to put multiple execution blocks inside the tag:


<executions>
<execution>
<id>copy-resources-AJS</id>
<!-- here the phase you need -->
<phase>validate</phase>
<goals>
<goal>copy-resources</goal>
</goals>
<configuration>
<outputDirectory>${basedir}/src/main/webapp/AJS</outputDirectory>
<resources>
<resource>
<directory>C:/Projects/lw/AJS/chapter1/angularApp</directory>
<filtering>true</filtering>
</resource>
</resources>
</configuration>
</execution>
<execution>
<id>copy-resources-A4</id>
<!-- here the phase you need -->
<phase>validate</phase>
<goals>
<goal>copy-resources</goal>
</goals>
<configuration>
<outputDirectory>${basedir}/src/main/webapp/A4</outputDirectory>
<resources>
<resource>
<directory>C:/Projects/lw/A4/chapter1/Angular4TypeScript/build</directory>
<filtering>true</filtering>
</resource>
</resources>
</configuration>
</execution>
<execution>
<id>copy-resources-A5</id>
<!-- here the phase you need -->
<phase>validate</phase>
<goals>
<goal>copy-resources</goal>
</goals>
<configuration>
<outputDirectory>${basedir}/src/main/webapp/A5</outputDirectory>
<resources>
<resource>
<directory>C:/Projects/lw/A5/chapter1/Angular5TypeScript/build</directory>
<filtering>true</filtering>
</resource>
</resources>
</configuration>
</execution>
</executions>

Make sure that each execution block has a unique ID, or else Maven will get confused. This copies my Angular 5 source files to:


${basedir}/src/main/webapp/A5

And they can be surfable using "http://localhost:port/A5/"

The Angular 4 source files to:


${basedir}/src/main/webapp/A4

And they can be surfable using "http://localhost:port/A4/"

And the AngularJS files will be put to:


${basedir}/src/main/webapp/AJS

And they can be surfable using "http://localhost:port/AJS/".

That is how you can copy multiple external directories into your Java project using Maven.

Why won't Jersey work on JDK 9?

I've been experimenting with writing REST Services in Java. A ton of clients have used Java to power their backend's over the years, but I never created a REST Service environment from scratch myself. I decided to tackle it during the holiday time and educate myself. I try to focus on front end programming technologies, but knowing about the backend is beneficial.

I decided to use Jersey to build out REST Services in Java and the road has been rocky.

I have a Maven project setup to use Tomcat 8.5 and Java 9.01. Unfortunately, I kept seeing a lot of errors like this in the Java console:


java.lang.IllegalArgumentException: Errors were discovered while reifying SystemDescriptor(
    implementation=org.glassfish.jersey.jaxb.internal.XmlRootObjectJaxbProvider$General
    contracts={javax.ws.rs.ext.MessageBodyReader}
    scope=javax.inject.Singleton
    qualifiers={}
    descriptorType=CLASS
    descriptorVisibility=NORMAL
    metadata=
    rank=0
    loader=null
    proxiable=null
    proxyForSameScope=null
    analysisName=null
    id=130
    locatorId=0
    identityHashCode=1215770148
    reified=false)
    at org.jvnet.hk2.internal.SystemDescriptor.reify(SystemDescriptor.java:705)
    at org.jvnet.hk2.internal.ServiceLocatorImpl.reifyDescriptor

etc.. etc..

or this:


java.lang.RuntimeException: java.util.concurrent.ExecutionException: java.lang.NoClassDefFoundError: javax/xml/bind/JAXBContext
    at org.glassfish.hk2.utilities.cache.LRUHybridCache.compute(LRUHybridCache.java:315)
    at org.glassfish.hk2.utilities.reflection.internal.ClassReflectionHelperImpl.getAllMethods(ClassReflectionHelperImpl.java:108)
    at org.glassfish.hk2.utilities.reflection.internal.ClassReflectionHelperImpl.getPreDestroyMethod(ClassReflectionHelperImpl.java:209)
    at org.glassfish.hk2.utilities.reflection.internal.ClassReflectionHelperImpl.access$400(ClassReflectionHelperImpl.java:56)
    at org.glassfish.hk2.utilities.reflection.internal.ClassReflectionHelperImpl$2.compute(ClassReflectionHelperImpl.java:74)
    at org.glassfish.hk2.utilities.reflection.internal.ClassReflectionHelperImpl$2.compute(ClassReflectionHelperImpl.java:70)
    at org.glassfish.hk2.utilities.cache.LRUHybridCache$OriginThreadAwareFuture$1.call(LRUHybridCache.java:115)
    at org.glassfish.hk2.utilities.cache.LRUHybridCache$OriginThreadAwareFuture$1.call(LRUHybridCache.java:111)
    at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:264)
    at org.glassfish.hk2.utilities.cache.LRUHybridCache$OriginThreadAwareFuture.run(LRUHybridCache.java:173)
    at org.glassfish.hk2.utilities.cache.LRUHybridCache.compute(LRUHybridCache.java:292)
    at
etc..etc..

They went on and on. Basically, some libraries that are required by Jersey are no longer included as part of the Java 9 SDK. They were there in Java 8, but were removed. These errors exist because the libraries cannot be found.

The trick to remove these errors is to load these libraries using Maven. Find the pom.xml that builds your project and find the dependencies section. It will probably look something like this:


<dependencies>
<dependency>
<groupId>org.glassfish.jersey.containers</groupId>
<artifactId>jersey-container-servlet-core</artifactId>
<!-- use the following artifactId if you don't need servlet 2.x compatibility -->
<!-- artifactId>jersey-container-servlet</artifactId -->
</dependency>
<dependency>
<groupId>org.glassfish.jersey.inject</groupId>
<artifactId>jersey-hk2</artifactId>
</dependency>
<!-- uncomment this to get JSON support
-->

<dependency>
<groupId>org.glassfish.jersey.media</groupId>
<artifactId>jersey-media-json-binding</artifactId>
</dependency>
</dependencies>

We need to add back in the missing dependencies. There are two libraries that were required:


<dependency>
<groupId>javax.xml.bind</groupId>
<artifactId>jaxb-api</artifactId>
<version>2.3.0</version>
</dependency>
<dependency>
<groupId>javax.activation</groupId>
<artifactId>activation</artifactId>
<version>1.1</version>
</dependency>

Relaunch your Tomcat instance and you are good to go. No errors and your Jersey services should work without issue.

All Content Copyright 2005, 2006, 2007, 2008, 2009 Jeffry Houser. May not be reused without permission
BlogCFC was created by Raymond Camden. This blog is running version 5.9.2.002.