Matt RaibleMatt Raible is a Web Developer and Java Champion. Connect with him on LinkedIn.

The Angular Mini-Book The Angular Mini-Book is a guide to getting started with Angular. You'll learn how to develop a bare-bones application, test it, and deploy it. Then you'll move on to adding Bootstrap, Angular Material, continuous integration, and authentication.

Spring Boot is a popular framework for building REST APIs. You'll learn how to integrate Angular with Spring Boot and use security best practices like HTTPS and a content security policy.

For book updates, follow @angular_book on Twitter.

The JHipster Mini-Book The JHipster Mini-Book is a guide to getting started with hip technologies today: Angular, Bootstrap, and Spring Boot. All of these frameworks are wrapped up in an easy-to-use project called JHipster.

This book shows you how to build an app with JHipster, and guides you through the plethora of tools, techniques and options you can use. Furthermore, it explains the UI and API building blocks so you understand the underpinnings of your great application.

For book updates, follow @jhipster-book on Twitter.

10+ YEARS


Over 10 years ago, I wrote my first blog post. Since then, I've authored books, had kids, traveled the world, found Trish and blogged about it all.

AppFuse 2.0 Status

Last week I managed to get AppFuse to compile with Maven 2, this week I got all the tests passing. As noted last week, one of the most frustrating things I found with Maven 2 is that WAR dependencies can't have .java/.class files that other projects can depend on. Because of this, I had to split each web/framework project into two: one that's packaged as a JAR and one that's packaged as a WAR.

I had a hard time deciding between the following directory structures:

1.

web
    - jsf
        - war

2.

web
    - jsf
war
    - jsf

3.

web
    - jsf
    - jsf-war

I ended up using the 3rd option because it seemed like the most intuitive for AppFuse developers. It's pretty ugly IMO, but it's also The Maven Way. To properly use convention-over-configuration, it's best not to go against the grain. The current directory structure can be seen by clicking here.

In an ideal world, I'd only need to do a single WAR project for each framework, and any classes compiled within the WAR would be available to child projects. However, WARs seem to be a strange beast in Maven. Not only can you not use a WAR's classes, but it doesn't seem like the dependency/exclusion mechanism works for WARs. This means that a WAR's dependencies have to be rather dumb, and they should only contain static files. Of course, AppFuse 2.0 could operate like it does now - where your project starts out with a bunch of files from the get-go. However, the problem with this setup is it makes it difficult to upgrade. The good news is using this new setup, you can create a project and use (and upgrade!) AppFuse pretty easily.

Below are the current steps (subject to change as we get closer to a release), assuming you already have Maven 2 and MySQL installed.

1. Create a directory and create a pom.xml file in it. The groupId, artifactId and version can be any values you choose. In pom.xml, add the following:

<project>
    <modelVersion>4.0.0</modelVersion>
    <groupId>com.mycompany</groupId>
    <artifactId>test-appfuse</artifactId>
    <packaging>war</packaging>
    <version>1.0</version>
    
    <build>
        <defaultGoal>package</defaultGoal>
        <plugins>
            <plugin>
                <groupId>org.mortbay.jetty</groupId>
                <artifactId>maven-jetty6-plugin</artifactId>
                <configuration>
                    <scanIntervalSeconds>3</scanIntervalSeconds>
                </configuration>
            </plugin>
        </plugins>
    </build>
    
    <repositories>
        <repository>
            <id>appfuse</id>
            <url>http://static.appfuse.org/repository</url>
        </repository>
    </repositories>
    
    <dependencies>
        <dependency>
            <groupId>org.appfuse</groupId>
            <artifactId>appfuse-struts-war</artifactId>
            <version>2.0-SNAPSHOT</version>
            <type>war</type>
        </dependency>
    </dependencies>
</project>

2. Download appfuse.sql and run the following commands.

mysqladmin -u root -p create appfuse
mysql -u root -p appfuse < appfuse.sql

If you already have an appfuse database, you'll need to drop that first. Note: the database name and type is hardcoded now, but you'll be able to change that when 2.0 is released, just like you can with AppFuse 1.x.

3. Run "mvn jetty6:run-war" and grab a beer (it's the weekend right?!). After everything has downloaded and started, login to your app with mraible/tomcat at http://localhost:8080/artifactId. If you get errors about missing dependencies, run the command again. If you get an error about web.xml from Jetty, run "mvn -U jetty6:run-war".

I've run into plenty of issues during this migration. I've listed them below and will likely add to this list over the next few days.

  • There is a DbUnit plugin for Maven 2, but I was only able to get it to work by checking it out from Subversion and building/installing it locally. Maybe I just have the wrong plugin repository, as it seems to be available here. Thanks to Brian Topping for writing this plugin - it works great!
  • The DbUnit plugin requires a sample-data.xml file for each project, as well as a fair amount of XML for its configuration. It would be nice to somehow use one sample-data.xml file and variables to configure. Maven's properties feature will probably work for configuring the variables.
  • The DbUnit plugin and Hibernate3 plugin are configured to run at the "compile-test" phase. Running "mvn -Dmaven.test.skip=true" still runs both plugins. Ideally, they would be skipped when this flag is on.
  • The "service" project has a hard-coded dependency on appfuse-hibernate. I need to figure out a way to have this project be dao-layer agnostic. This will likely require that tests don't load up applicationContext-hibernate.xml, or there's a test for each DAO option.
  • Any tests (in service and web) that talk to a database load up "classpath*:/applicationContext-hibernate.xml". Ideally, I could load up "classpath*:/applicationContext-*.xml", but this doesn't work when loading context files from JARs. Therefore, the context file packaged in JARs is likely going to have to be generic, possibly named applicationContext-dao.xml.
  • Many of the tests in web/JAR projects depend on i18n properties files, or XML files in WEB-INF (i.e. faces-config.xml and action-servlet.xml for Spring/WebWork). To make them pass, I had to copy files from the WAR projects into the JAR projects' src/test/resources directory. Obviously, duplicate files between projects is a bad thing, so hopefully tests can be re-worked to eliminate duplication.
  • The maven-jetty6-plugin for Maven 2 works great, the (newer) maven-jetty-plugin does not.
  • Because WARs are overlaid, "mvn jetty6:run" cannot be used w/o running "mvn war:inplace" first. Using "mvn jetty6:run-war" or "jetty6:run-exploded" works, but doesn't auto-refresh files when you edit/save them in your IDE. Possible workarounds include:
    • Modifying the Jetty plugin to support overlaid WARs
    • Configuring IDEs to auto-deploy files into the target/WAR directory upon save
    • Running "mvn war:inplace" first
    I don't like the 3rd option because it's often difficult to tell which files are from your project and which ones are from the overlaid WAR.
  • Since scope=provided and scope=test are not added to the classpath for child projects, there's a lot of dependency duplication between web/*/pom.xml files. I doubt there's a workaround for this.
  • I still need to hook Cargo in and get Canoo WebTests running.
  • Tapestry only allows global-i18n files to be loaded from WEB-INF, therefore, I have to have duplicate i18n files in WEB-INF and src/main/resources. The reason is some service classes expect i18n files to be in the classpath. This is a Tapestry issue and not a Maven one.
  • I need to figure out a way to have the logj4.xml in the final WAR be the one used, or make sure it isn't included at the root of any appfuse-* JARs.

If you're interested in seeing AppFuse 2.0 from a developer's perspective, you can download it in its current form from:

http://static.appfuse.org/downloads/appfuse2-20060826.zip

Please keep in mind that this is still very much in the "proof of concept" phase, so any advice is most welcome. CollabNet has scheduled our CVS to SVN migration for Monday, so hopefully I can checkin everything after that.

Posted in Java at Aug 26 2006, 02:41:26 PM MDT 7 Comments
Comments:

The artifactId of jetty pluging is deprecated:

<plugin> 
        <groupId>org.mortbay.jetty</groupId> 
        <artifactId>maven-jetty-plugin</artifactId>
</plugin>

And the invocation should be:

mvn jetty:run

or

mvn jetty:run-war

Posted by dahernan on August 27, 2006 at 04:09 AM MDT #

Uppps I don't see this:

"The maven-jetty6-plugin for Maven 2 works great, the (newer) maven-jetty-plugin does not."

Yesterday I test maven-jetty-plugin with equinox and works great :S

Posted by dahernan on August 27, 2006 at 04:19 AM MDT #

how to change the password of mysql root user, in your case is no password,thanks

Posted by lane.ma on August 28, 2006 at 12:15 AM MDT #

I'm assuming you mean for the dbunit plugin? If you're trying to build AppFuse, it tries to run dbunit, even when you skip the tests. The issues with this are noted in the 2nd and 3rd bullets above. The user/pass are currently hardcoded (to test/test) in each pom, but should be extracted to the parent pom.xml. If you run "ant setup-db" with AppFuse 1.9.3, you should be able to use that same database with this build of 2.0.

Posted by Matt Raible on August 28, 2006 at 10:30 AM MDT #

Dear Matt, I am getting serious now in Maven after trying Lightbody's Able. All the idea of POM really amazing. Currently reading WebWork in Action. You pointed me in the right direction. Thanks a lot.

Posted by Eko SW on August 28, 2006 at 12:28 PM MDT #

One thing must be recognized:
- The distribution is damn small now :).

When do you plan to apply this on the main trunk?
At least to get rid of the huge /lib :) ?

Thanks in advance,

Ahmed.

Posted by Ahmed Mohombe on August 29, 2006 at 08:44 AM MDT #

Matt, I agree that WARs are strange beasts in Maven 2, and I've had similar problems developing a series of related web applications. I thought the WAR plugin supported WAR dependencies, but i also remember running into problems. Another solution wold be to have these WAR projects publish an assembly with a qualifier.

Posted by Tim O'Brien on September 28, 2008 at 09:10 AM MDT #

Post a Comment:
  • HTML Syntax: Allowed