Thursday, October 6, 2011

Oracle Releases A Developer Preview JDK 7 for Mac OS X

At JavaOne 2011 Oracle announced the availability of JDK 7 for Mac OS X Developer Preview.

Go to http://jdk7.java.net/macportpreview/ for the download.

A list of open issues can be found here.

I as an eclipse fanboy am also happy about the release of Eclipse Indigo SR1 which adds full Java 7 support. Go here to see what is new for Java 7 in Eclipse Indigo SR1.

To use newly installed JDK in Eclipse, you have to add the path to the JDK home manually. Start Eclipse with JDK 6, select "Installed JREs" -> "Add.."->"Standard JVM". Enter the path to the /Contents/Home folder inside the installed JDK bundle and provide a meaningful name:




Have fun while trying out the latest Java 7 features!

Saturday, July 23, 2011

Project Voldemort Version 0.9

More than one year after the 0.8.1 release, LinkedIn just released version 0.9 of it's scalable nosql database Project Voldemort.

Go here for the release notes.

Sunday, July 17, 2011

Generic Java Methods And Type Inference

To create test data in Java I often wrote things like this:
List<String> names = new ArrayList<String>();
names.add("Tick"); 
names.add("Trick");
names.add("Track");
...
Generic methods and type inference make this task a lot easier:
public static <T> List<T> newArrayList(T... entries) {
  return new ArrayList<T>(Arrays.asList(entries));
}
The following JUnit test shows how to use this code:
public class ListBuilderTest {

  @Test
  public void test() {
    List<String> l = ListBuilder.newArrayList("Tick", "Trick", "Track");
      assertThat(l.size(), equalTo(3));
      assertThat(l, hasItem("Tick"));
      assertThat(l, hasItem("Trick"));
      assertThat(l, hasItem("Track"));
    }
}

By the way: I love the JUnit 4 org.junit.matchers.JUnitMatchers.* and org.hamcrest.CoreMatchers.* Matchers :-)

Of course you do not have to implement this code yourself. You can for example use the great guava libraries.

Monday, June 6, 2011

How To Update A File In A Jar/War Archive

Sometimes you want to update a file bundled in a jar or war archive (e.g. a config file).
In this post I am going to show how to update the file config/app-conf.xml in a war called frontend.war by using the jar-command.

To list the contents of our jar archive we type the following:

jar tf frontend.war

To extract the config file from the archive, type

jar xf frontend.war config/app-conf.xml

This creates a folder named config with the file app-conf.xml inside. Now you can edit the config file. After you are done editing the file you can update the archive by typing

jar uf frontend.war config/app-conf.xml

For having a quick look at the contents of a file you can use the unzip command:

unzip -q -c frontend.war config/app-conf.xml
(the c switch redirects output to stdout, the q(uiet) switch suppresses all other output. That's all!

Sunday, May 22, 2011

How To Install The MySQL Gem On Mac OS

For my latest ruby on rails project I had to install the MySQL gem on my laptop with Mac OS 10.6.
I had some trouble with this. Finally the following command did the trick:

gem install mysql -- --with-mysql-config=/usr/local/mysql/bin/mysql_config

Update: For rails 3 it is advisable to use the mysql2 gem.

Sunday, May 15, 2011

How To Send Emails With The Lift Framework

The Lift Framework has built in support for sending emails by the Mailer class. Lift leverages the Java Mail API to send mails.

If you want to use Mailer in your application (for example for user registration via MegaProtoUser), Lift needs to know, which smtp server to use for sending mails. By default it tries to use a mail server on localhost, port 25. If you want to use a different server or if your mail server requires password authentication, you have to provide configuration values for Mailer.

There are several ways to configure the Mailing System:
  • Use system properties
  • Use Lift properties
  • Use a mail session from the JNDI context of your container

Configuring Mailer by system properties

To keep things short: I do not recommend this. Use Lift properties. They are way more flexible.

Configuring Mailer by Lift properties

Lift properties allow you to provide configuration values for different run modes of your application. You can provide different values for development, test, staging, pilot, production or profile mode.

To configure Mailer for development, simply put this

mail.smtp.host={your mail host here}

into src/main/resources/default.props. Production values can be provided in the file production.default.props. In general the naming scheme for Lift property files is modeName.userName.hostName.props with hostName and userName being optional. For development, the modeName is empty.

The port of your SMTP host can be specified by the property mail.smpt.port.
Usually you do not have to change this, since 25 is the default port for SMTP servers.

During development it can be useful to enable the debug mode for the mailing system. This can be done by setting mail.debug=true in your props file.

If your mailserver requires password authentication, some extra work needs to be done. You need to provide the username and the password in the configuration file:

mail.user={your username here}
mail.password={your password here}

In Boot.scala you need to create an authenticator:

...
import javax.mail.{ Authenticator, PasswordAuthentication }
import net.liftweb.util.{ Mailer, Props }
...

class Boot {
  def boot {
    ...  
    Mailer.authenticator = (Props.get("mail.user"), Props.get("mail.password")) match {
      case (Full(u), Full(p)) => Full(Authenticator {
        override def getPasswordAuthentication = new javax.mail.PasswordAuthentication(u, p)
      })
      case _ => Empty
    }
    ...
  }
}

This sets up password authentication for your mail session. The drawback of this solution is that you have to provide your SMTP credentials in your configuration files.


Use a mail session from the JNDI context of your container

Your Lift application runs in a servlet container like Jetty or Tomcat. Servlet containers allow you to create mail sessions in the JNDI context of your container. This means the servlet container handles the creation of the mail session and the application simply requests the pre-configured session from the container.

To create a mail session in Jetty, put this into your jetty.xml:

<configure class="org.mortbay.jetty.webapp.WebAppContext" id="wac">
...
<new class="org.mortbay.jetty.plus.naming.Resource" id="mail">
     <arg><ref id="wac"></ref></arg>
     <arg>mail/Session</arg>
     <arg>
       <new class="org.mortbay.naming.factories.MailSessionReference">
         <set name="user">YOUR_USERNAME</set>
         <set name="password">OBF:2xmk4B261z0f3f1c1xsR</set>
         <set name="properties">
           <new class="java.util.Properties">
             <put name="mail.smtp.host">YOUR_MAIL_HOST</put>
             <put name="mail.debug">true</put>
           </new>
          </set>
       </new>
     </arg>
</new>
</configure>

mail/Session is the name of the mail session, that can be used to reference the session from your application.

This example uses jetty's password obfuscation feature to avoid plain text paswords in your configuration files. More information about configuring JNDI mail sessions in jetty can be found here.

To use the session in your application, put the following code into your web.xml:

<resource-ref>
  <description>Mailer Session</description>
  <res-ref-name>mail/Session</res-ref-name>
  <res-type>javax.mail.Session</res-type>
  <res-auth>Container</res-auth>
</resource-ref>

This code tells your application, that a javax.mail.Session is available under the name mail/session. The res-auth Container part says, that the container handles authentication for this resource.

To configure Lift's mailer with this mail session, simply put the following code into your Boot.scala:

...
import net.liftweb.util. Mailer
...

class Boot {
  def boot {
    ...  
    Mailer.jndiName = Full("mail/Session")
    ...
  }
}

There is one last thing you have to do in order to get JNDI mail sessions with Lift Mailer working:

If you configure a mail JNDI-session in your servlet container, the mail session is created with classes loaded form the mail.jar in your container. If your application also includes mail.jar, you will run into classpath issues and Mailer will not work. Because of this, you will have to exclude the transitive dependencies on mail.jar declared by some lift modules as lift-proto, lift-mapper and lift webkit.

If you are using sbt, the following code in your Project.scala excludes the transitive dependency of lift-mapper to mail.jar from your project. The dependency on mail.jar with scope "provided" includes mail.jar into your classpath during development but the jar will not be included in your war file.

override def ivyXML =
    <dependencies>  
      <dependency name="lift-mapper_2.8.1" org="net.liftweb" rev="{liftVersion}"> 
        <exclude name="mail" org="javax.mail">
        </exclude>
      </dependency>
    </dependencies>  

  val mail = "javax.mail" % "mail" % "1.4" % "provided->default"

The line declaring the original dependency on lift-mapper has to be removed.

If you are using maven, the following code in you pom.xml excludes the transitive dependencies on mail.jar:

<dependency> 
    <groupid>javax.mail</groupid> 
    <artifactid>mail</artifactid> 
    <version>1.4.1</version> 
    <scope>provided</scope> 
</dependency> 
<dependency> 
  <groupid>net.liftweb</groupid> 
  <artifactid>lift-mapper_2.7.7</artifactid> 
  <version>2.1-SNAPSHOT</version> 
  <exclusions> 
    <exclusion> 
        <groupid>javax.mail</groupid> 
        <artifactid>mail</artifactid> 
    </exclusion> 
  </exclusions> 
</dependency> 


After this configuration change you have to run the commands reload and update in sbt.

Now Mailer should be working with the JNDI mail session.

Using JNDI mail sessions with sbt

Since sbt version 0.7.5 you can also use JNDI mail sessions when running jetty from sbt. To use this feature, you have to declare the following dependencies in your project definition.

val jetty6 = "org.mortbay.jetty" % "jetty" % "6.1.22" % "test->default"  
  val jetty6plus = "org.mortbay.jetty" % "jetty-plus" % "6.1.22" % "test->default"  
  val jetty6naming = "org.mortbay.jetty" % "jetty-naming" % "6.1.22" % "test->default"  

Then specify the path to your jetty-configuration:

override def jettyEnvXml = Some( 
  (sourcePath / "main" / "jetty" / "jetty-env.xml").asFile

Now you can put your JNDI-configuration into this file.

Sunday, February 13, 2011

Hibernate Mode on Macbook Pro with OptiBay

Recently i bought an OptiBay Drive for my Macbook Pro. The OptiBay Drive allows you to replace your Superdrive with another hard disk or SSD.

I used the OptiBay to install an Intel X25 SSD on my Computer. I put the os on the SSD. After that, the system really works fast. This article has a video comparing an old macbook pro with hard disk to an old macbook pro with SSD. The article is in german, but you will understand the included video without knowledge of german.

But after the installation of the os on the SSD i had a problem: when i put the machine on standby it froze. I had to power of the machine and restart it. After some research if found out, that by default, mac os uses the "sleep and hibernate" mode for standby.

In sleep mode, the ram content is maintained. Of course this works only as long as there is power to maintain the ram contents. Waking up the machine from sleep mode is very fast.

In hibernate mode, the ram content is written to the hard disk. The content can be restored even if the battery fully died.

"Sleep and hibernate" mode means the machine goes to sleep mode but for safety reasons the disk content is also written to the hard disk.

For some reasons, entering hibernate mode only works if the ram content is written to the primary disk. But since i installed the os on the (secondary) SSD, the system tries to write the ram contents to the secondary disk. When doing this the system freezes.

First i tried to move the hibernate file to another disk. This is possible, the file is written when the system goes to standby. But when you try to wake up the system after a power loss, the system boots from scratch and does not restore the state which was written to the hibernate file. The reason for this is that the hibernate file must be on the root volume.

I solved the problem by changing the hibernate mode from "sleep and hybernate" to "sleep". This can be done with the pmset command:
sudo pmset hibernatemode 0
Now the system can be put in standby mode again!. The only drawback of this solution is that the current state can not be restored after a power loss (e.g. battery was empty).

As a last step you can recover some disk space on your ssd and remove the hibernate file. It is not used anymore.
sudo rm /var/vm/sleepimage