Showing posts with label eclipse. Show all posts
Showing posts with label eclipse. Show all posts

Monday, April 29, 2013

Efficient Structural Analysis of existing projects - part 1


Introduction

As a software engineer you already might have run in the following situation: A legacy application needs to be extended, and most of the initial developers have either left or work on new projects. Documentation is sparse and the code base is huge - but you need to quickly understand the structure of the project, or at least the parts you're about to change. How can you possibly achieve that?

Structural analysis to the rescue

Under structural analysis we understand the analysis of:
  • project structure
  • project elements
  • elements structure
  • elements relations
We will have a general overview of those aspects below - the description refers mainly to two object oriented languages: Java and C#. The details we will present in a series of blog posts - so stay tuned for more!

Analysis of project structure

A typical project is composed of:
  • modules
    • packages / namespaces
      • elements (classes)
So first it is required to understand what modules are included in the project and what their roles are. Additionally one also has to understand how elements (classes) are organized within modules - what packages / namespaces are there and what elements do they contain.

Analysis of project elements

In Java and C# projects, elements of the following kinds/categories can be found:
  • class
    • interface
      • annotation (Java)
    • attribute (C#) - equivalent to annotation in Java
    • enum
    • throwable / exception 1)
    • array
    • delegate (C#)
  • struct (C#)
1) logical category

Analysis of elements structure

Java and C# classes can contain the following members:
  • attribute
    • field
    • constant 1)
  • operation
    • method
    • constructor
    • finalizer / destructor 2)
  • property 1)
    • indexer (C#)
  • operator (C#)
  • event (C#)
  • nested element
1) logical category in Java, language-level category in C#
2) logical category in both languages - should not be used anymore

Analysis of element relations

An element can have any of the following relations:
  • outbound
    • generalization
    • abstractions
    • nestings
    • associations
      • uni-directional
      • bi-directional
      • aggregations
        • compositions
    • dependencies
  • inbound
    • specializations
    • realizations
    • nesting owner
    • association usages
      • aggregation usages
        • composition usages
    • dependency usages

Structural analysis of a sample Java project

Now imagine that you start working on an existing project: ScrumToys, an application to support conducting projects in SCRUM. Below you can see 2 screenshots from the application.

Figure 1a. ScrumToys application - dashboard showing stories and tasks of sample project sprint.

Figure 1b. ScrumToys application - editing of sample task.


Figure 1a shows stories and tasks. Tasks are grouped into 3 categories, according to their status: TODO, DOING, DONE. Figure 1b shows the task edit dialog.

Your role is to modify the application. You've received the following assignment:

  • add next task status-category: APPROVED
  • remove inconsistency in the name of task status: DOING (Figure 1a) and WORKING (Figure 1b) - it should be WORKING on all screens across the system (also on those not shown on screenshots)
  • make task status changeable - currently it cannot be changed (Figure 1b)

In order to do your assignment correctly, you have to understand the structure of the application - at least of the parts related to the given tasks. Let's see a comparison on how popular software engineering tools can support you in your assignment.



Tools


The following software engineering tools are chosen to help us with the structural analysis:


1) officially not supported on Eclipse 4

Analysis


Project structure

First, we would like to have general overview of the project structure:
Figure 2a. Project structure in Eclipse IDE.

Figure 2b. Project structure in NetBeans IDE.

Figure 2c. Project structure in IntelliJ IDEA.

Figure 2d. Project structure in Class Visualizer.

As shown in Figure 2, two out of four tools (IntelliJ IDEA and Class Visualizer) present graphical information about the kind of element (class, interface, enum, annotation) and one of them (Class Visualizer) presents the full list of project elements. All tools except Eclipse IDE show the structure of the element currently selected on the list.
The analysis of the element structure and its relations will be discussed in next parts of this series.

Friday, March 20, 2009

JBoss Seam Hot Deploy with Maven - Update

I just published an updated version of the Seam Hotdeploy Maven Plugin (see my previous post here). For a detailed description on how to use it, have a look at the Google Code Wiki. I also updated the sample Maven POM featuring JBoss Seam 2.1.1.GA.

The new version should be easier to configure and play nicer with e.g. the Eclipse Maven plugin (I'm not using NetBeans/IntelliJ too often, but I hope this works also fine there). The new Eclipse builder configuration looks like shown in the image below:



Note: The Eclipse Maven plugin using its embedded Maven had somehow problems with the extended lifecycle of the Hotdeploy Plugin. Using an external Maven installation (2.0.10) felt not only faster but was also not having problems with it.

Saturday, December 6, 2008

Using JBoss Seam Hot Deployment with a Maven Build

[UPDATE: The new plugin version is documented here]

As you might have read in previous posts, one of our favorite web application stacks consists of JBoss Seam. While combining this with our favorite tooling suite consisting of Eclipse and Maven, we had to realize that Seam has a much longer tradition with Ant, and Maven support is only slowly moving in. Today I want to share some ideas on how to tackle the combination issues.


While JBoss Tools provides a nice code hot deployment feature when working with Seam on JBoss, things can get a little hairy when using a Maven build with the project. Seam uses a special classloader and relies on monitoring the WEB-INF/dev folder for changed classes - where Maven is completely unaware of this and uses the standard WEB-INF/classes folder to deploy all classes in the project. More than once I've seen the situation where JBoss Tools and Maven got in each others way, ending with JBoss rejecting to restart the application due to "duplicate components". The reason was that Eclipse hot deployed classes to WEB-INF/dev where Seam expects them, but Maven being completely unaware of it packaging all classes in the common WEB-INF/classes folder.

In order to avoid trouble and also to allow using hot deployment from a command line build, I experimented with several approaches to achieve hot deployment with Maven. The main challenges here are:
  • Distinguishing compiler output: The Maven compiler plugin by default compiles everything in the same output folder. We need to be able to distinguish between hot and regular deployable code.
  • Publish updated resources to JBoss, including domain model classes, seam components as well as XHTML pages.
  • Make sure Seam unit tests still compile.
The solution I came up with was to write a new Maven plugin which extends the Maven compiler plugin with a new hotdeploy:compile goal and the following functionalities (source code as well as a simple Maven 2 repository is available in our Google Code account):
  • Hook into the compile phase and compile the source code to a dedicated directory. The source code location is configurable as well as the output directory.
  • Remove outdated hot deployable class files from the JBoss deployment. This is necessary for the Seam classloader to pick up the changes, only updating the file is not enough.
The plugin configuration is straight forward as it's based on the regular compiler plugin and is shown in the XML snippet below. Note that it is recommended to create a profile for this build setup as both your continuous build as well as your operations team might not care too much about using hot deployment.
<plugin>
<groupId>com.ctp.seam.maven</groupId>
<artifactId>maven-hotdeploy-plugin</artifactId>
<version>0.1.0</version>
<configuration>
<source>${java.source.version}</source>
<target>${java.source.version}</target>
<hotdeployOutputDirectory>${directory.hotdeployables}</hotdeployOutputDirectory>
<includes>
<include>**/session/**</include>
</includes>
<deployDirectory>
${directory.deploy.jboss}/${build.finalName}.${project.packaging}
</deployDirectory>
</configuration>
<executions>
<execution>
<phase>compile</phase>
<goals>
<goal>compile</goal>
</goals>
</execution>
</executions>
</plugin>

The main additions to a regular compiler plugin setup are:
  • This variant uses the common /src/main/java source folder and uses in- and excludes to distinguish the hot deployable sources. Alternatively you can set the sourceDirectory configuration value pointing to a dedicated source folder (similar as JBoss Tools does the setup for you). Don't forget that this requires then the Build Helper Maven plugin to add source folders to your regular build.
  • The deployDirectory is a reference to your exploded application directory inside the JBoss deploy folder. This is needed in order to remove outdated hot deployable classes.
  • You can specify the hotdeployOutputDirectory directory where the code should be compiled to. Note that this defaults to the value shown in the example - feel free to skip this part. The plugin will compile into this folder after appending a WEB-INF/dev to the path.
The rest of the setup we can do by simply reconfiguring existing plugins. Note the Google Code Wiki contains a complete sample POM ready for you to start your own Seam webapp. The details on the configuration are:
  • Reconfiguring the WAR plugin so the webappDirectory points inside our JBoss deploy folder. Maven uses this folder to assemble the WAR file, which perfectly corresponds to an exploded deployment. Additionally we define our hot deployment compilation folder as a webResource, which will copy our compilation exactly to the WEB-INF/dev folder in the exploded deployment.

<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-war-plugin</artifactId>
<configuration>
<webResources>
<resource>
<directory>${directory.hotdeployables}</directory>
<filtering>false</filtering>
</resource>
</webResources>
<webappDirectory>
${directory.deploy.jboss}/${build.finalName}.${project.packaging}
</webappDirectory>
</configuration>
</plugin>

  • Similarly, we have to add our output folder to the test classpath. This is simplest done by adding it as a resource folder, which will copy the classes to the target/test-classes directory before the test classes are compiled:
<testResources>
<testResource>
<directory>${directory.hotdeployables}/WEB-INF/dev</directory>
<filtering>false</filtering>
</testResource>
...
</testResources>

If you want to run a similar luxury setup as you get from JBoss Tools, you can add a Maven builder to your project. Simply go to the Eclipse Project properties and click "New" on the "Builders" properties. The new Maven build should look like the following:



Make sure that the following conditions apply to your Eclipse setup:
  • The JRE you have configured is actually a JDK - otherwise the builder will fail. Once you see that the builder does not fail, you can also switch off the console allocation in the "Common" tab.

  • Also take care that you always build with your specific hot deploy profile - otherwise make sure to clean before using the build again.

  • Assert that Eclipse uses a dedicated output folder and not the Maven target/classes.

Unfortunately when activating the builder Eclipse might prompt you when editing files and (depending on the speed of your machine) hang for a second or two after saving a file. Still, this is much better than waiting a minute for your JBoss server to restart.

Happy coding!

Tuesday, June 10, 2008

Targeting JBoss Seam for Multiple Application Servers

Not all application servers are equal - something you realize quickly in a consultant's life working in different customer environments. The "developer friendliness" varies broadly here - I guess waiting for the container to deploy, go down and up again is a phenomenon many of the web developers out there know too well...

A stack that works for me very efficient is JBoss Seam on JBoss application server. Since its integration with JBoss Tools, the code-deploy cycle goes extremely smooth. But how can we leverage this while targeting other application servers?

After some experiments, I came up with a solution based on Maven. In general, the deployment of Seam distinguishes in library dependencies and some config files. For example is Hibernate the default persistence provider on JBoss, but not on WebLogic - but using Hibernate has the advantage of using Hibernate Validators, which integrates in Seam very comfortable with JSF validation. Maven allows to create different profiles, which contain different dependency sets tailored for another application server. The differences for running Seam in different containers are well described in the Seam documentation.

pom.xml:
<profiles>
<profile>
<id>weblogic10</id>
<dependencies>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate</artifactId>
<version>${hibernate.version}</version>
<exclusions> ... </exclusions>

...

</profile>
</profiles>
Integrating this in JBoss Tools turnes out to be a little trickier. The best approach seemed to be to start with a Seam project wizard in the Maven source structure:
  • Java Source Directory: src/main/java
  • Content Directory: src/main/webapp
The project needs then to be 'mavenized' by adding the Eclipse Maven 2 plugin if not already installed and a POM to the project. Getting the dependencies correct can be a little tedious with all the exclusions - best is to add just one by one and compare with the Web App Libraries that come out of the wizard. Once this is done, the libraries in WEB-INF/lib can be deleted and the Maven dependencies added in the Project J2EE Dependencies dialog. As a nice side-effect, this Maven setup makes it extremely easy to upgrade your libraries. For example, upgrading RichFaces from 3.2.0 to 3.2.1 was just a 1-character change in the POM!

We have now a clean separation between dependencies, but still the config files need different treatments. I went for a solution on adding three subfolders to src/main/resources:
  • common for, well, common resource files like message bundles and Drools rule files
  • jboss and e.g. weblogic for the files requiring different versions for applications servers, namely the components.xml and persistence.xml files (using Hibernate on WebLogic 10 requires a different configuration - the transaction manager lookup and the query factory class need to be changed).
This works now fine in JBoss Tools and you can start coding. Still, to run the Maven build we need some additional fixes as we changed the Maven default structure on the source files (JBoss Tools uses src/main/java/action and src/main/java/model) and on the resources:

pom.xml:
<build>
<sourceDirectory>
${basedir}/src/main/java/model
</sourceDirectory>
<plugins>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>build-helper-maven-plugin</artifactId>
<executions>
<execution>
<id>add-source</id>
<phase>generate-sources</phase>
<goals>
<goal>add-source</goal>
</goals>
<configuration>
<sources>
<source>${basedir}/src/main/java/action</source>
</sources>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
This configures the two source folders in JBoss Tools - a little verbose, but Maven usually knows only one source folder. For the resource folders, we need to configure the build settings in the distinct Maven profiles:

pom.xml:
<build>
<resources>
<resource>
<directory>src/main/resources/common</directory>
</resource>
<resource>
<directory>src/main/resources/weblogic</directory>
</resource>
</resources>
</build>
We can now test for example the WebLogic profile in a continuous build, deploying the WAR file on an integration server.

The resulting project structure in Eclipse is shown in the screenshot below: