Sunday, 19 February 2012

JDK7 EJB3.1 and Netbeans Project (Part I) - Introduction

Part I - Introduction, Part II - Hibernate and Transactions, Part III - Testing

Introduction


I've tasked myself with learning the new things available to JDK 7 and EJB 3.1 and how they integrate with Netbeans. In order to so do, in my experience, it is most gratifying to pick up a new project using these new technologies.

In this case, as at the time, I was wondering what to do with my old Photographs, I've decided to start up a project called YourPersonalPhotographOrganiser, which is nothing more than a simple Photo Gallery.

You can find the netbeans project on github at https://github.com/maartenl/YourPersonalPhotographOrganiser. Just check it out into your ~/NetBeansProjects/YourPersonalPhotographOrganiser directory, and see how far you get.

It's a work in progress, but it's at the stage where there's something more or less workable. Let me remind you that this software is for use at your own risk. Use it locally, as there is NO security (neither authentication nor authorization) implemented at the moment.

Requirements


  1. simple database, easy to make changes directly, if so required
  2. used for home use
  3. no authentication or authorization required
  4. helps me to understand the jdk 7, glassfish and jee 3.1, by using all the new stuff in there.
  5. absolutely NO changing of the photographs, all changes are done in java, in memory, in glassfish.*
  6. flexible in where these photographs are located (no need to keep them in the webdir, for example)

*) I've had too many instances where:
  1. changing files from webinterface is a security risk, and requires proper access rights.
  2. changing files causes the extra data present in the jpegs put there by photocameras to be discarded
  3. changing files potentially causes deterioration of the quality of the jpegs
  4. changing files has sometimes caused the file to be damaged in some way
  5. changing files makes it impossible to determine if the photo is already present in your collection

Technical

Some of the (new) stuff that is being used.
  1. JDK7 (Look for "JDK7" in the sourcecode)
    1. multiple catch
    2. try-with-resources
    3. new switch statement
    4. diamond-notation
    5. filevisitor interface
    6. Path class usage
  2. EJB 3.1
    1. no local interfaces on beans
    2. EJBs inside the WAR, no longer is an EAR required
    3. Improved Context and Dependency Injection
  3. Netbeans IDE 7.0.1.
  4. GlassFish Server Open Source Edition 3.1.1 (build 12).
  5. JPA (Hibernate)
  6. REST (Jersey)
  7. MySQL
  8. JQuery
  9. HTML, CSS, JavaScript and AJAX
  10. JSON

Database Schema

The database schema below shows the used Hibernate Entities. They have the same name as the tables. The database script below should run without errors on your average MySQL database.
drop table if exists Log;
drop table if exists Tag;
drop table if exists Comment;
drop table if exists GalleryPhotograph;
drop table if exists Gallery;   
drop table if exists Photograph;
drop table if exists Location;

create table Location (
 id bigint not null auto_increment primary key,
 filepath varchar(512)
);

create table Photograph (
 id bigint not null auto_increment primary key,
 location_id bigint not null,
 filename varchar(255),
 relativepath varchar(1024),
 taken timestamp,
 hashstring varchar(1024),
 filesize bigint,
 angle int,
 foreign key (location_id) references Location (id)
);

create table Gallery (
 id bigint not null auto_increment primary key,
 name varchar(80),
 description text,
 creation_date timestamp not null default current_timestamp,
 parent_id bigint,
 highlight bigint,
 sortorder int not null,
 foreign key (parent_id) references Gallery (id),
 foreign key (highlight) references Photograph (id)
);

create table GalleryPhotograph (
 id bigint not null auto_increment primary key,
 gallery_id bigint not null,
 photograph_id bigint not null,
 name varchar(255),
 description text,
 sortorder bigint,
 foreign key (gallery_id) references Gallery (id),
 foreign key (photograph_id) references Photograph (id)
);

create table Comment (
 id bigint not null auto_increment primary key,
 galleryphotograph_id bigint not null,
 author varchar(255),
 submitted timestamp,
 comment text,
 foreign key (galleryphotograph_id) references GalleryPhotograph (id)
);

create table Tag (
 tagname varchar(80) not null,
 photograph_id bigint not null,
 primary key (tagname, photograph_id),
 foreign key (photograph_id) references Photograph (id)
);

create table Log (
 id bigint not null auto_increment primary key,
 jobdate timestamp not null default current_timestamp,
 joblog blob not null
);

-- only allows a photograph to appear once in a gallery
create unique index unique_per_photograph_per_gallery
on GalleryPhotograph (gallery_id, photograph_id);

Update 1: Moved angle field from GalleryPhotograph over to Photograph
Update 2: It's nice to have a script for creating the database, but an ORM can automatically generate the proper tables for you if you like.

Saturday, 11 February 2012

PlantUML and NetBeans

If you're looking to integrate PlantUML with Netbeans with Maven, check out my blogpost here.

Introduction


One of the problems with software designers is that they do not enjoy writing Documentation. I do, but then again, I'm weird.

Now Documentation in the area of Java can be split up into two categories:
  • Javadoc comments, that reside in the Java source code, right where it matters
  • Specs, design documents, etc. which are made when the system is first designed and are then stored on a network drive or (if you're lucky) a version control system. They are never updated, become outdated, and forgotten but are sometimes used to provide new junior designers with a wrong idea of the architecture.
So, ideally, you'd wish to have all the specs on hand in the same fashion as your javadoc, with the hope that any change in the code by dilligent designers is also propagated in the javadoc.6

This is where I find PlantUML1 to be extremely handy.

Installing PlantUML in Netbeans


The following task addition lifted straight from the pages of PlantUML and added to build.xml in the netbeans project.
<!-- task definition -->
<taskdef name="plantuml"
  classname="net.sourceforge.plantuml.ant.PlantUmlTask"
  classpath="plantuml.jar" />


<!-- process ./src files -->
<target depends="javadoc-build" name="build-uml">
    <mkdir dir="${dist.javadoc.dir}/images"/>
    <!-- there is an issue where relative paths do not work -->
    <plantuml output="/home/mrbear/NetBeansProjects/YourProject/${dist.javadoc.dir}/images/" verbose="true">
        <fileset dir="./src">
            <include name="**/*.java" />
            <exclude name="**/*Test.java" />
        </fileset>
    </plantuml>
</target>
This won't work, as plantuml.jar cannot be found automatically. Once you've downloaded it you can let your project know where it is. A good explanation of this can be found at [3].

Running PlantUML and Javadoc


First of all, we add the uml syntax2 to the javadoc comments.
/**
 *
 * <p>Indicates the different sizes that are possible in the displaying
 * of pictures. BIG being un-scaled.</p>
 * <img src="../../images/ImageSize.png"/>
 * @author maartenl
 *
 * @startuml
 * "java.lang.Enum<ImageSize>" <|-- enum ImageSize
 * ImageSize : +ImageSize BIG
 * ImageSize : +ImageSize LARGE
 * ImageSize : +ImageSize MEDIUM
 * ImageSize : +ImageSize THUMB
 * ImageSize : +getHeight()
 * ImageSize : +getWidth()
 * @enduml
 */

public enum ImageSize
{

Build the "build-uml" target. It will automatically generate all the javadocs and start off generating uml diagrams. You can do this in the Files explorer in netbeans, right-click on build.xml on toplevel and select the appropriate run target. When the "build-uml" ant target is started in netbeans, the following output is shown:

main:
Starting PlantUML
Nb images generated: 1
BUILD SUCCESSFUL (total time: 0 seconds)

The webpage will look like the image below![5] VoilĂ , uml diagrams!

Issues

- Two files have the same name, so they both create the same named image file. And they get copied in the ant task, so only one of them remains!

The easiest solution is to add a filename after the "@startuml" command, to indicate the name of the image. This is especially important if you have two or more diagrams within the same Java file. I found it especially convenient when dealing with UML diagrams in package-info.java files.

A better solution would be to update the Ant task to take care of this automatically.

- I'm getting "taskdef class net.sourceforge.plantuml.ant.PlantUmlTask cannot be found using the classloader AntClassLoader[]"!

Make sure the plantuml.jar file is reachable in the classpath.

- Auto formatting in Netbeans of my Java source code throws my carefully created UML specs in the Javadoc into disarray!

Yes, while Eclipse has a /* @formatter:on */ editor annotation, I have been unable to find the same in Netbeans.

For now, the only solution I have found it to turn on 'explicit newlines' in formatting of the javadoc comments. You can do this by going in Netbeans to Tools->Options->Editor->Formatting->select Java->Category Comments and turn on "Preserve New Lines".

- The image shows errors, something like the image below.
Dot Executable: /usr/bin/dot
File does not exist
Cannot find Graphviz. You should try

@startuml
testdot
@enduml

or

java -jar plantuml.jar -testdot

It means you haven't installed the graphviz4 package that takes care of a lot of rendering.

root@localhost:~# apt-get install graphviz
Reading package lists... Done
Building dependency tree       
Reading state information... Done
The following extra packages will be installed:
  libcgraph5 libgvpr1
Suggested packages:
  graphviz-doc
The following NEW packages will be installed:
  graphviz libcgraph5 libgvpr1
0 upgraded, 3 newly installed, 0 to remove and 197 not upgraded.
Need to get 553 kB of archives.
After this operation, 1,741 kB of additional disk space will be used.
Do you want to continue [Y/n]? y
Get:1 http://nl.archive.ubuntu.com/ubuntu/ natty/main libcgraph5 i386 2.26.3-5ubuntu1 [47.8 kB]
Get:2 http://nl.archive.ubuntu.com/ubuntu/ natty/main libgvpr1 i386 2.26.3-5ubuntu1 [198 kB]
Get:3 http://nl.archive.ubuntu.com/ubuntu/ natty/main graphviz i386 2.26.3-5ubuntu1 [307 kB]
Fetched 553 kB in 0s (563 kB/s) 
Selecting previously deselected package libcgraph5.
(Reading database ... 163396 files and directories currently installed.)
Unpacking libcgraph5 (from .../libcgraph5_2.26.3-5ubuntu1_i386.deb) ...
Selecting previously deselected package libgvpr1.
Unpacking libgvpr1 (from .../libgvpr1_2.26.3-5ubuntu1_i386.deb) ...
Selecting previously deselected package graphviz.
Unpacking graphviz (from .../graphviz_2.26.3-5ubuntu1_i386.deb) ...
Processing triggers for man-db ...
Setting up libcgraph5 (2.26.3-5ubuntu1) ...
Setting up libgvpr1 (2.26.3-5ubuntu1) ...
Setting up graphviz (2.26.3-5ubuntu1) ...
Processing triggers for libc-bin ...
ldconfig deferred processing now taking place
Thank the Heavens that I'm still running an old Ubuntu, that downloads the proper (read: old) version of GraphViz. PlantUML, I hear, has issues with the new and improved GraphViz 2.28. 1 2

Unfortunately, I was unable to use a relative path in the output attribute in the build.xml. I hope I can fix this later.

Update: changed ImageSizeEnum to ImageSize. Naming should not contain data type names, according to uncle Bob.

Second Update
: PlantUML according to this now works with the newest Graphviz version.

Third Update: Updated NetBeans javadoc formatting problem with a better solution.

References

[1] PlantUML
http://plantuml.sourceforge.net/
[2] Drawing UML with PlantUML - Language Reference Guide (Version 5737)
http://sourceforge.net/projects/plantuml/files/PlantUML%20Language%20Reference%20Guide.pdf/download
[3] NetbeansFAQ
http://wiki.netbeans.org/FaqAntJunitJar
[4] Graphviz
http://www.graphviz.org/
[5] Example
http://maartenl.github.com/YourPersonalPhotographOrganiser/javadoc/gallery/enums/ImageSize.html
[6] "To keep documentation maintained, it is crucial that it be incorporated in the source program, rather than kept as a separate document ... even high-level language syntax does not at all convey purpose." [DRY principle]
The Mythical Man-Month (Frederick P. Brooks, Jr.)