Java Package for Release in Netbeans

I had to create a Package for Release for a Netbeans-ANT-Class Project including

  • the javadoc (inside a doc folder)
  • the sources (bundled inside a jar)
  • as well as the jar-file it self.

To make it a bit automated, I extend the ant build script file “build.xml”. It is located in the root-folder of the netbean project. I create a new property (proj.version) and two new targets (package-sources, release_package). So it looks like this:

<!-- ... -->
   <!-- project-properties (last defaults, set them in project.properties!) -->
   <property name="proj.version" value="1.2.0" />

    <target description="bundle sources in a jar" name="package_sources">
        <jar basedir="src" destfile="build/release/${application.title}-${proj.version}-sources.jar"/>
    </target>

    <target name="release_package" depends="jar,javadoc,package_sources">
        <mkdir dir="build/release"/>
        <copy file="${dist.jar}" todir="build/release/"/>
        <mkdir dir="build/release/doc"/>
        <copy todir="build/release/doc">
            <fileset dir="dist/javadoc" includes="**"/>
        </copy>

        <zip basedir="build/release/" includes="**" destfile="dist/${application.title}-${proj.version}.zip"/>
    </target>

 </project>

To start the creation process, I call the release_package target by ant. The easiest way (as so far as I know) to do this, is

  1. Goto Files Register in Netbeans (on the leftside)
  2. Right-Click on the build.xml file
  3. Select “Run Target” –> “Other Targets” –> “release_package”

This should create inside the dist-folder from your project the new release zip-file.

 

GlassFish Log to MySQL Database

To make the GlassFish Logfile (normally stored at ${com.sun.aas.instanceRoot}/logs/server.log) a bit more reusable, I have created a loghandler to print out all entries into a MySQL database. It tooks me a while to understand, how can I do this. So I will share the knowledge with you.

I created a new LogHandler which extend java.util.logging.Handler.

/*
 * Created tdmarti, HSLU T+A - D3S (2011)
 */
package ch.hslu.edu.loghandler;
 
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.util.logging.Handler;
import java.util.logging.LogRecord;
import java.util.logging.SimpleFormatter;
 
/**
 *
 * A Loghandler which write the GlassFish Log file into a MySQL Database
 * 
 * @author tdmarti
 */
public class GlassFishMySQLHandler extends Handler {
 
    private final String driverName = "com.mysql.jdbc.Driver";
    private String connURL = "jdbc:mysql://localhost:3306/logger";  //default value
    private String username = "admin";                              //default value
    private String password = "adminadmin";                         //default value
 
    private Connection connection;
 
    protected final static String insertSQL = "insert into GlassFishLog (level,"
            + "logger,message,sequence,"
            + "sourceClass,sourceMethod,threadID,timeEntered)"
            + "values(?,?,?,?,?,?,?,?)";
    protected final static String clearSQL = "delete from GlassFishLog;";
    protected PreparedStatement psmtInsert;
    protected PreparedStatement psmtClear;
 
    /**
     * Default Constructor.
     * Create a connection to the Database. Following properties can be set
     * <code>
     * -Dch.hslu.edu.loghandler.connURL
     * -Dch.hslu.edu.loghandler.username
     * -Dch.hslu.edu.loghandler.password
     * </code>
     */
    public GlassFishMySQLHandler() {
        try {
            // check and load properties
            if ( (System.getProperty("ch.hslu.edu.loghandler.connURL")) != null) {
                connURL = System.getProperty("ch.hslu.edu.loghandler.connURL");
            }
            if ((System.getProperty("ch.hslu.edu.loghandler.username")) != null){
                username = System.getProperty("ch.hslu.edu.loghandler.username");
            }
            if ((System.getProperty("ch.hslu.edu.loghandler.password")) != null){
                password = System.getProperty("ch.hslu.edu.loghandler.password");
            }
 
            Class.forName(driverName);
 
            connection = DriverManager.getConnection(connURL, username, password);
            psmtInsert = connection.prepareStatement(insertSQL);
            psmtClear = connection.prepareStatement(clearSQL);
        } catch (ClassNotFoundException ex) {
            System.out.println("ClassNotFoundException: " + ex);
        } catch (SQLException ex) {
            System.out.println("SQLException: " + ex);
        }
    }
 
    /**
     * Write out the log entry to the database.
     * @param record
     */
    @Override
    public void publish(LogRecord record) {
        if (! isLoggable(record)) {
            return;
        }
        String message = record.getMessage();
        if (message == null) {
            return;
        }
        if ((getFormatter() == null) ||
             (getFormatter().getClass() != (new SimpleFormatter()).getClass())) {
            setFormatter(new SimpleFormatter());
        }
        try {
            message = getFormatter().formatMessage(record);
        } catch (Exception ex) {
            System.out.println(ex.toString());
        }
 
        try {
            psmtInsert.setInt(1,          record.getLevel().intValue());
            psmtInsert.setString(2, trunc(record.getLoggerName(), 200));
            psmtInsert.setString(3, trunc(message, 255));
            psmtInsert.setLong(4,         record.getSequenceNumber());
            psmtInsert.setString(5, trunc(record.getSourceClassName(), 200));
            psmtInsert.setString(6, trunc(record.getSourceMethodName(), 200));
            psmtInsert.setInt(7,          record.getThreadID());
            psmtInsert.setLong(8,         record.getMillis() );
            psmtInsert.executeUpdate();
        } catch (Exception ex) {
            System.out.println(ex.toString());
        }
    }
 
    /**
     * Make a commit.
     */
    @Override
    public void flush() {
        try {
            connection.commit();
        } catch (SQLException ex) {
            Logger.getLogger(GlassFishMySQLHandler.class.getName()).log(Level.SEVERE, null, ex);
        }
    }
 
    /**
     * Close the Connection.
     * If the conneciton already closed, nothing will happen.
     * @throws SecurityException
     */
    @Override
    public void close() throws SecurityException {
        try {
            if (connection != null) {
                connection.close();
            }
        } catch (SQLException ex) {
            System.out.println(ex.toString());
        }
    }
 
    /**
     * Truncate a String, to the max lenght.
     *
     * @param str
     * @param length
     * @return
     */
    private String trunc(String str, int length) {
        if (str == null)
            return "";
        if (str.length() &lt; length) {
            return str;
        }
        return (str.substring(0, length));
    }
 
    /**
     * truncate the table.
     * Remove all entries inside the table
     *
     */
    public void clear() {
        try {
            psmtClear.executeUpdate();
        } catch (SQLException ex) {
            System.out.println(ex.toString());
        }
    }
}

According to this, I created a new database-table like this

  CREATE TABLE GlassFishLog (
      `id` INT(11) NOT NULL AUTO_INCREMENT PRIMARY KEY,
      sourceClass VARCHAR(200) DEFAULT NULL,
      sourceMethod VARCHAR(200) DEFAULT NULL,
      threadID VARCHAR(200) DEFAULT NULL,
      timeEntered BIGINT DEFAULT NULL,
      `level` VARCHAR(200) DEFAULT NULL,
      logger VARCHAR(200) DEFAULT NULL,
      message VARCHAR(255) DEFAULT NULL,
      `sequence` VARCHAR(200) DEFAULT NULL
  );

That is almost all. The last step was to configure the GlassFish Application Server (v3.1) to use this Log Handler as follow:
In the webgui goto: Configurations -> server-config -> Logger Settings
Edit and extend the property “Log Handler”: with your new LogHandler. My property looks like:

java.util.logging.ConsoleHandler, ch.hslu.edu.loghandler.GlassFishMySQLHandler

Edit the jvm settings to configure the Database Connection
Goto: Configurations -> server-config -> JVM Settings
Select the “JVM Options” tab an create 3 new values as follow:

 -Dch.hslu.edu.loghandler.connURL="jdbc:mysql://localhost:3306/logger"
 -Dch.hslu.edu.loghandler.username="sa"
 -Dch.hslu.edu.loghandler.password="1234"

This solution is not perfect, but it fullfil my requirements. Known Issues are:

  • The Database Server has to be running and reachable by GlassFish, else GlassFish can not start up
  • You can not configure the driver

Service Status

Today has been one of These days, nothing wanted to work on the first go, everything behaved differently than expected or information was just not where it was expected, but by the end of the day almost every thing was running or running again.

 

Services – Subversion, Redmine, WordPress, Git

A few have probably noticed performance issues with one of our services in past few days, being it the blog, redmine, git or svn – just to let you know upfront: these where all related. As many of you hopefully already know, most of our systems run Solaris and on these we use Solaris Zones (or containers if you prefer) to get dedicated environments for most of our services. So even though it might not look like it all the above services share (or better shared) the same physical host. Usually this setup works quite well for us, at least it has during the last 4-5 years but in the recent past trouble arose. It startet out with Subversion/Apache suddenly producing log files of sizes of hundreds of megabytes to a few gigabytes a day, already then it was quite clear that the new build-servers, used in class, were the main reason for this but as I couldn’t easily change the build-servers I just fixed the logging of Apache and the log rotation a bit and for a moment everything seemed fine again. Until yesterday… wow it’s already this late… so it was the day before yesterday ;-) , when some people started to notice long waiting times for one or the other of these services so I had a look again and noticed right a way that the system hosting these zones had I load average of between 30 and 40 – in my opinion in this case just way to much! So the decision was made do move some of the services to a separate host – dev on one and git, blog and pm on the other, but first I turned my attention to the build-servers. It turns out they where polling Subversion each minute for each build project, together with the students accesses that was just too much for our meager V210 system, so I changed this schedule to every 5 minutes… – here was one of the points where stuff just didn’t want to work out, but telling this story in detail too would go to far – and almost like magic the load on the system dropped and the responsiveness of the other services was also way better again. Still, to avoid SVN impacting the other services again I moved them off to another host and we’re making sure that the build-servers will start using svn post-commit-hooks instead of polling to further reduce the load.

 

EEEnet – the Experimental Enterprise Environment Network

A few weeks ago our Lab was one of the first to be connected the the new EEEnet, a network which in the near future should connect all the different laboratories of all the school departments with as few barriers as possible. A second “Lab” that was added around the same time, is the new HPC Cluster of the department of Mechanical Engineering. We’ve already been maintaining their “old” Cluster and there they have been using some of our services (proxy, mail server, ssh gw, etc.) so they would have liked to do the same on the new cluster. But it turns out it was not just a setting in our firewall which was needed to allow access to do so, no, it was routing troubles again and figuring out routing problems around firewalls for some of which you don’t know the settings and rule sets, I’m telling you, can be a pain in the a**. This one is still an open task and a clean solution would be much appreciated, as our network can be quite confusing as it is and definitely doesn’t need anymore quirks which make it harder to understand :-) .

 

let’s see what the next week brings.

News!(?)

As most of you will have noticed – I’m not the biggest blogger but today I felt like I had to write again.

Every once in a while I have to try new stuff and today is such a day. For a few tests that I want to do I’ll need a complete lab environment, meaning:

  • Intranets and DMZ(s)
  • Master & Slave DNS Servers
  • Firewalls
  • a Proxy
  • a LDAP Server
  • NTP Server
  • Hosts (for the things I actually want to test)
  • and later maybe also a DHCP and a AI Server

For such a test setup I would usually setup a few virtual machines and configure them appropriately, but for various reasons not this time. For one I have to say I love VMware Fusion on my Mac but when it comes to handling multiple internal (host-only) networks there’s sadly just no easy way to manage that (yet)… it would be doable and to be frank dedicated networks are not strictly necessary for this setup anyways but I want them and I want to try something new. So I decided to give Solaris 11 Express a go and have a look at project Crossbow and the new zone features (as this stuff will come in handy for new Lab exercises anyway).

At the moment I’m planning to setup the whole environment in one Solaris 11 VM creating a dedicated zone for each service. The whole network shall be built by employing the new vnic and etherstub constructs, so it will resemble a physical setup as closely as possible.

So over the next few days I hope to be able to setup this infrastructure and keep you up-to-date with the progress, but for now that’s it.

Setup GlassFish 3.1 on Ubuntu

After the ENAPP lecture in the last term, I had some cleanup efforts. One of them is to move a server system from a windows- to a linux system. Here a small summary.

They are a few Tutorial how to Setup a Glassfish as a service on a Ubuntu. The best post I have found was from nabisoft. Unfortunately, I only found this blog post after I have already configurated my system. For my own configuration I used this wiki-page from nextsource.se. It works as well as the one from nabisoft, but without the firewall security stuff (iptables, etc.) and less documentation. I hope I can do the iptable things later…

Additional to this blog post, I had to do following:

Change Glassfish Admin password

go to the webgui (localhost:4848) and click on Domain -> Administration Password (Tab on the right) and change it

Change JMS Service Type

As I will use the GlassFish OpenMQ from other Computers than only this Server, I had to change the Java Message Service Type to LOCAL. This means that, it will be started with GlassFish, but not in the same JVM as the GlassFish Server.

Change OpenMQ Broker Password

The command to change the password is:
root@ubuntu:/opt/glassfishv3/mq/bin# ./imqusermgr update -u admin -a true -p myNewPassword

Don’t forget to adjust the password in the glassfish webgui (Configurations -> server-config -> Java Message Service -> JMS Hosts -> default_JMS_host)

It is quite easy, as long you don’t use exclamation mark in the password! It tooks me more than a half day to figure out, that OpenMQ don’t accept exclamation mark. If you use an exclamation mark, OpenMQ accept them first, but after it can’t start up. Else you get the very good (warning sarcasm) error message:
[#|2011-03-02T20:19:29.748+0100|WARNING|glassfish3.1|javax.jms|_ThreadID=10;_ThreadName=Thread-1;|[C4003]: Error occurred on connection creation [localhost:7676]. - cause: java.net.ConnectException: Connection refused|#]