June 10, 2009

Hello Project Darkstar! in Netbeans and Eclipse

With Project Darkstar's new distribution structure (introduced in version 0.9.8 and explained here), people ask from time to time what the best way is to setup a project in Netbeans or Eclipse. I think the typical answer that you see the most fits the acronym "TMTOWTDI" (There's More Than One Way To Do It). This is true but not necessarily very helpful. In the hopes of eliminating some pain I'm here to offer a way to setup a project in these IDE's (but this should by no means be considered the way).

First, here is a quick description of the project and the tools that I will be using:
  • This will be a purely server side project that will print "Hello Project Darkstar!" when the server is booted.
  • I will be using Maven as the build tool for the project.
  • The project will leverage the Project Darkstar Maven Plugin to aid in deploying, booting, and shutting down the server according to the new distribution format for the official Project Darkstar server package.
  • It should be possible to build, run, and test the raw project outside of an IDE, within Netbeans, and also within Eclipse (with a few tweaks for each respective IDE).
There are three source files that are of interest in this project. The first is the actual Java source file that represents the main class for the server. This class should look something like this:
package my.pkg.hello;

import java.io.Serializable;
import java.util.Properties;
import java.util.logging.Level;
import java.util.logging.Logger;
import com.sun.sgs.app.AppListener;
import com.sun.sgs.app.ClientSession;
import com.sun.sgs.app.ClientSessionListener;

public class HelloProjectDarkstar implements AppListener, Serializable {
  private static final long serialVersionUID = 1L;
  private static final Logger logger = 
      Logger.getLogger(HelloProjectDarkstar.class.getName());

  public void initialize(Properties props) {
    logger.info("Hello Project Darkstar!");
  }

  public ClientSessionListener loggedIn(ClientSession session) {
    return null;
  }
}

Second, it is strongly recommended for a Project Darkstar application that you include an app.properties file in the META-INF directory of your resulting JAR file.  This file will be used as the base set of configuration properties for the server and is a good place to include default values for application specific configuration properties.  In our simple example, we'll include just two required properties, the name of the server and the listener class:

com.sun.sgs.app.name=HelloProjectDarkstar
com.sun.sgs.app.listener=my.pkg.hello.HelloProjectDarkstar

Third, you need a Maven POM file.  If you're unaware of how Maven works, you can read up on it at the Maven website.  Essentially, the POM file is used to declaratively describe your project's resources and dependencies.  Maven then uses this information to correctly build it.  Our project has only one dependency (the sgs-server-api) so our POM file should look something like this:

  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
                      http://maven.apache.org/maven-v4_0_0.xsd">
  4.0.0

  my.package.hello
  hello-projectdarkstar
  0.1-SNAPSHOT
  Hello Project Darkstar
  jar

  
    
      com.projectdarkstar.server
      sgs-server-api
      ${sgs-server.version}
    
  

  
    
      
      
 org.apache.maven.plugins
 maven-compiler-plugin
 
   1.6
   1.6
 
      
    
  

  
    0.9.9
  

  
    
      java.net
      java.net Maven2 Repository
      http://download.java.net/maven/2/
      default

These three files should be organized in a directory structure that looks something like this:
- hello-projectdarkstar
  - pom.xml
  - src
    - main
      - java
        - my
          - pkg
            - hello
              - HelloProjectDarkstar.java
    - resources
      - META-INF
        - app.properties

At this point you should be able to build a JAR file that is deployable in a Project Darkstar server. Since this is a Maven project, this should be possible:
  • From outside an IDE using the command mvn package
  • From within Netbeans (ensure that you have the Maven plugin installed, then try "Open Project" and Netbeans should automatically detect that the root folder is a Maven project)
  • Or from within Eclipse (ensure that you have the Maven plugin installed, then choose "Import" from the File menu and import as a "Maven project").
This is all a good first step, but in order to boot up our server, we still need to manually take the JAR file that is built by Maven, deploy it into a Project Darkstar server, and then fire up the server. This is tedious, and we'd rather be able to do this using one command (or one click from the IDE). Enter the Project Darkstar Maven plugin. The plugin is pretty well documented on its website, but essentially what it does is automate the process of taking your built JAR file, deploying it into a Project Darkstar container, configuring the container with the appropriate configuration files, and then booting up the server. It also includes the capability to shutdown a running server. Using this, therefore, we can automate the process of running our Project Darkstar application by simply adding a configuration entry for this plugin into our POM in a separate Maven profile:
  
      run-server
      
 
          
            com.projectdarkstar.maven.plugin
            sgs-maven-plugin
            1.0-alpha-3
            
              
                sgs-run
                pre-integration-test
                
                  install
                  configure
                  deploy
                  boot
                
              
            
            
              ${sgs-server.version}
              
                ${project.build.directory}/sgs-server-dist-${sgs-server.version}
              
              ${basedir}/conf/hello.boot
              ${basedir}/conf/hello.properties
              
                ${project.artifact.file}

This configuration combines the install, configure, deploy, and boot goals of the sgs-maven-plugin into one. Also notice that there are two additional configuration files that are included in your source tree under the conf directory, hello.boot and hello.properties. These files are respectively used to replace the sgs-boot.properties and sgs-server.properties configuration files in the main Project Darkstar distribution. We can keep these files simple for now, but any set of valid configuration properties can be included:

# hello.boot
# =======
JAVA_OPTS = -server -Xmx768M

# hello.properties
# =======
com.sun.sgs.app.root=data

So we now have a complete project that looks something like this:
- hello-projectdarkstar
  - conf
    - hello.boot
    - hello.properties
  - pom.xml
  - src
    - main
      - java
        - my
          - pkg
            - hello
              - HelloProjectDarkstar.java
    - resources
      - META-INF
        - app.properties
The project can be built inside or outside of Netbeans or Eclipse using the same mechanisms as described above. However, with this additional configuration, we can also automatically build, deploy, and boot the application in a Project Darkstar container by simply activating the run-server Maven profile. When this is done, Maven will build the project JAR file, download and install the Project Darkstar distribution into the project's target directory, deploy the built JAR file into the Project Darkstar installation, copy the hello.boot and hello.properties configuration files into the Project Darkstar installation conf directory, and then boot up the server using the sgs-boot.jar from the Project Darkstar installation. This is completely automated and requires doing just the following for each of our respective environments:
  • From outside any IDE: just run the command mvn verify -Prun-server. Shutting down the server requires simply a Ctrl-C. Also, in order to clean out the Project Darkstar datastore in between executions, it is necessary to run mvn clean.
  • From Netbeans: You should configure the properties of the project by right clicking the project and selecting the "Properties" option. Configure a new Action (or one of the existing actions like the "Run" action) to run the verify goal with the run-server profile activated. Then you should be able to boot up the server by executing that specific action for your project (Right click the project and choose "Run" or whatever action you created under the "Custom" menu). In order to shutdown the server, you should also configure an additional action (i.e. Stop) that runs the sgs:stop goal with the run-server profile activated. Prefer using this action to shutdown the server rather than just killing the process (since multiple JVMs are started when Project Darkstar boots).
  • From Eclipse: Similar to Netbeans, you need to configure two "Run Configurations", one that runs the verify goal with the run-server profile activated, and one that runs the sgs:stop goal with the run-server profile activated. These two configurations should be respectively used to bootup and shutdown the server.
There are a lot more sophisticated ways that you can setup your project with the Project Darkstar Maven plugin that allows you to customize the runtime environment from the command line. You can also tweak it to support booting multi-node configurations by modifying the boot configuration file, or use filterable properties to customize these values at runtime. I won't get into these here, but I would suggest looking at Project Snowman's server POM for some ideas. Hopefully, though, this post should give you enough to get the ball rolling in setting up your development environment for a Project Darkstar application.

10 comments :

  1. Hi!

    What do you mean by "Enter the Project Darkstar Maven plugin"? Do I have to download and install this manually or is it already included in the normal Maven plug-in? And how do I enter it? Opening a certain file in the explorer? Or can/should I do it through Eclipse?


    Cheers,
    MEDooSA

    ReplyDelete
  2. Sry for the doublepost, but I forgot to mention something.

    When using Eclipse, I normally create a new project, create a new package in the src folder, create my classes into the package etc. pp.

    Now, this'd lead me to a folderstructure like this:
    |-HelloProjectDarkstar
    |-src
    |..|-my.pkg.hello
    |..|...|-HelloProjectDarkstar.java
    |..|-ressources
    |......|-META-INF
    |.........|-app.properties
    |-pom.xml

    So I don't have the main and java folder like they're shown in your tutorial. Does that matter? Do I have to create them manually?


    Cheers,
    Thomas

    ReplyDelete
  3. I think most people starting toying around with darkstar would like a single IDE run command that shutdowns any existing server, cleans the database and boots a new server.

    ReplyDelete
  4. There is an error in the blog post.

    The resources directory should be under the main directory, not the src directory. Otherwise the default resources maven compiler will not find it, and the app.properties will not be included in the jar file.

    ReplyDelete
  5. You can add:



    java.net
    java.net Maven2 Repository
    http://download.java.net/maven/2/
    default



    The first time you run to find the sgs-maven-plugin.

    ReplyDelete
  6. -pluginRepositories-
    -pluginRepository-
    -id-java.net-id-
    -name-java.net Maven2 Repository-name-
    -url-http://download.java.net/maven/2/-url-
    -layout-default-layout-
    -pluginRepository-
    -pluginRepositories-

    ReplyDelete
  7. first of all i want thank owen for the great work.

    still, i had a few problems with the article,
    one of them has a hint in the previous respond,
    the final pom.xml of this example is some kind of a mystery, at least for me which most of these stuff are new, i have done some reading about maven to understand whats going in there,
    for these who want the shortcut, here is the final result of the pom.xml:

    http://pastebin.com/fd037ca

    ReplyDelete
  8. I was able to get it to work (thanks to all of you). So far I can run "Maven Package" and it compiles the jar for me but I can't get the "run-server' profile section to work. Can someone please elaborate how to run it? I'm using my-eclipse 8 with maven4myeclipse.

    My pom.xml looks like this (as mentioned in the above post)
    http://pastebin.com/fd037ca


    Any help would be greatly appreciated as I'm stuck on this part.

    ReplyDelete
  9. Hello, could someone please paste his/her actual pom.xml? This one says "Missing artifact com.projectdarkstar.server:sgs-server-api:jar:0.9.9:compile"
    Thanks a lot

    ReplyDelete