Popular Posts

Sorry. No data so far.

Ben McCann

Co-founder of Connectifier.
Investor at C3 Ventures.
Google and CMU alum.

Ben McCann on LinkedIn Ben McCann on AngelList Ben McCann on Twitter

Commons Math vs. ojAlgo

01/23/2011

There are numerous math libraries for Java.   This is frustrating as a user because it’s hard to decide which to use.   Sometimes an algorithm is implemented in one library, but not another, which means you must marshal your data between proprietary formats.  I was working on solving systems of linear equations and there was no good Java-only solution available, so I had to write my own.  I decided to contribute the SimplexSolver to Commons Math because it used a friendly license and because it already had significant mindshare.  After doing so, I was informed that ojAlgo has a LinearSolver as well.  Today I decided to test it out to see whether I’d wasted my time by writing my own implementation.  It turns out that the ojAlgo implementation is buggy as shown by the unit test below which I created.

package com.benmccann.test;

import static org.ojalgo.constant.BigMath.EIGHT;
import static org.ojalgo.constant.BigMath.FIVE;
import static org.ojalgo.constant.BigMath.FOUR;
import static org.ojalgo.constant.BigMath.ONE;
import static org.ojalgo.constant.BigMath.SEVEN;
import static org.ojalgo.constant.BigMath.SIX;
import static org.ojalgo.constant.BigMath.TEN;
import static org.ojalgo.constant.BigMath.TENTH;
import static org.ojalgo.constant.BigMath.THREE;
import static org.ojalgo.constant.BigMath.TWO;
import static org.ojalgo.constant.BigMath.ZERO;

import java.math.BigDecimal;
import java.util.List;

import org.junit.Assert;
import org.junit.Test;
import org.ojalgo.matrix.BasicMatrix;
import org.ojalgo.matrix.store.PhysicalStore;
import org.ojalgo.matrix.store.PrimitiveDenseStore;
import org.ojalgo.optimisation.OptimisationSolver;
import org.ojalgo.optimisation.Variable;
import org.ojalgo.optimisation.OptimisationSolver.Result;
import org.ojalgo.optimisation.linear.LinearExpressionsModel;

public class SolverTest {

  @Test
  public void testMath286() {

    Variable[] objective = new Variable[] {
        new Variable("X1").weight(TENTH.multiply(EIGHT)),
        new Variable("X2").weight(TENTH.multiply(TWO)),
        new Variable("X3").weight(TENTH.multiply(SEVEN)),
        new Variable("X4").weight(TENTH.multiply(THREE)),
        new Variable("X5").weight(TENTH.multiply(SIX)),
        new Variable("X6").weight(TENTH.multiply(FOUR))};

    LinearExpressionsModel model = new LinearExpressionsModel(objective);
    model.setMaximisation(true);

    model.addWeightExpression("C1",
            new BigDecimal[] { ONE, ZERO, ONE, ZERO, ONE, ZERO }
        ).level(new BigDecimal(23));
    model.addWeightExpression("C2",
            new BigDecimal[] { ZERO, ONE, ZERO, ONE, ZERO, ONE }
        ).level(new BigDecimal(23));
    model.addWeightExpression("C3",
            new BigDecimal[] { ONE, ZERO, ZERO, ZERO, ZERO, ZERO }
        ).lower(TEN);
    model.addWeightExpression("C4",
            new BigDecimal[] { ZERO, ZERO, ONE, ZERO, ZERO, ZERO }
        ).lower(EIGHT);
    model.addWeightExpression("C5",
            new BigDecimal[] { ZERO, ZERO, ZERO, ZERO, ONE, ZERO }
        ).lower(FIVE);

    Result result = model.getDefaultSolver().solve();
    List solution = result.getSolution()
        .getRows(new int[] { 0, 1, 2, 3, 4, 5 })
        .toPrimitiveStore().asList();

    // A valid solution of 25.8 can be produced with:
    //     X1=10, X2=0, X3=8, X4=0, X5=5, X6=23
    // However, ojAlgo returns 21.7
    Assert.assertEquals(25.8, solution.get(0) * .8 + solution.get(1) * .2
        + solution.get(2) * .7 + solution.get(3) * .3
        + solution.get(4) * .6 + solution.get(5) * .4, .1);
  }

}

After releasing the Common Math SimplexSolver, I received numerous bug reports, which has been the main benefit of open sourcing it.  The code is now more robust as a result.  The test above was just one of many cases that Commons Math initially had trouble with, so I don’t fault the ojAlgo developers for getting it wrong the first time around – I did too.  However, I’m glad I chose to contribute to a well-recognized project because it led to flushing out many of these problems.  A lesser known project such as ojAlgo doesn’t have that advantage.  I’m not sure why so many people are still writing their own smaller libraries instead of contributing to make the larger players better.  Hopefully ojAlgo will consider recommitting its efforts towards Commons Math or another of the larger projects at some point.  It would be good for the community to see some consolidation.  At one point, matrix-toolkits-java was talking about combining with Commons Math, which would be a great move towards consolidated APIs.

MySQL Commands Cheatsheet

01/22/2011
Install SQL Buddy
sudo apt-get install apache2 libapache2-mod-php5 php5-mysql
sudo /etc/init.d/apache2 restart

Download SQL Buddy, unzip, and move to /var/www

  • Set the bind address in /etc/mysql/my.cnf to your ip address
  • Open the port in the firewall by running “/sbin/iptables -A INPUT -i eth0 -p tcp –destination-port 3306 -j ACCEPT” followed by “iptables-save”
  • Grant privileges on remote host as shown below
Login via MySql client:
$ mysql -u XXXXX -pXXXXX db_name
Create a new user:
CREATE USER 'user1'@'localhost' IDENTIFIED BY 'pass1';
GRANT ALL ON *.* TO 'user1'@'localhost';
CREATE USER 'user1'@'%' IDENTIFIED BY 'pass1';
GRANT ALL ON *.* TO 'user1'@'%';
List users:
select host, user, password, Create_priv from mysql.user;
List databases and tables:
show databases;
show tables;
Rename column:
ALTER TABLE Article change article_id id bigint(20);
Make column non-null:
ALTER TABLE Person MODIFY firstName varchar(255) NOT NULL;
Make column unique:
ALTER TABLE Person ADD UNIQUE INDEX(memberId);
Calculate the database size:
SELECT table_schema "DB Name", sum(data_length + index_length) / 1024 / 1024  "DB size in MB" FROM information_schema.TABLES GROUP BY table_schema;

Embedded Jetty

01/19/2011

One of the coolest things about Jetty is the ability to run it in embedded mode.  This means that you can write a Java app with a main method that will launch a Jetty server.  This has some really nice benefits.  For example, it makes it really easy to deploy a server to EC2 because all you need to do is transfer your jar file there and hit run – no need to setup a servlet container, etc.  Also, it makes it possible to dynamically set servlet parameters such as Struts 2 devMode.  You can set a flag on the command line, parse it using a library such as JCommander, and then run in development mode depending upon what was requested by the flag passed in.

You first need to get the relevant jars included in your project as dependencies. All of the dependencies are available in Maven repositories. I use Gradle, so you may not be familiar with the syntax below, but you can take the parts between the colons and enter them as the groupId, artifactId, and version if you’re using Maven.

  compile 'org.eclipse.jetty:jetty-io:8.0.0.M3'
  compile 'org.eclipse.jetty:jetty-server:8.0.0.M3'
  compile 'org.eclipse.jetty:jetty-servlet:8.0.0.M3'
  compile 'org.eclipse.jetty:jetty-util:8.0.0.M3'
  compile 'org.eclipse.jetty:jetty-webapp:8.0.0.M3'
  compile 'org.mortbay.jetty:jsp-2.1-glassfish:2.1.v20100127'

Here’s an example of running a web app in Jetty’s embedded mode:

package com.benmccann.example.server;

import java.net.URL;

import org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.handler.ErrorHandler;
import org.eclipse.jetty.server.nio.SelectChannelConnector;
import org.eclipse.jetty.servlet.ErrorPageErrorHandler;
import org.eclipse.jetty.servlet.FilterHolder;
import org.eclipse.jetty.servlet.FilterMapping;
import org.eclipse.jetty.servlet.ServletHandler;
import org.eclipse.jetty.webapp.WebAppContext;

import com.google.inject.Guice;
import com.google.inject.Injector;
import com.google.inject.servlet.GuiceFilter;

/**
 * @author benmccann.com
 */
public class WebServer {

  private final Server server;

  public WebServer() {
    this.server = createNewServer();
  }

  private Server createNewServer() {
    Server server = new Server();

    SelectChannelConnector connector = new SelectChannelConnector();
    connector.setPort(8080);
    server.addConnector(connector);

    WebAppContext webApp = new WebAppContext(getBaseUrl(), "/");
    webApp.addEventListener(new GuiceListener());

    ServletHandler handler = createServletHandler();
    webApp.setServletHandler(handler);
    webApp.setErrorHandler(createErrorHandler());
    server.setHandler(webApp);

    return server;
  }

  private ErrorHandler createErrorHandler() {
    ErrorPageErrorHandler errorHandler = new ErrorPageErrorHandler();
    errorHandler.addErrorPage(500, "/error.html");
    return errorHandler;
  }

  private ServletHandler createServletHandler() {
    ServletHandler servletHandler = new ServletHandler();

    FilterHolder guiceFilterHolder = createGuiceFilterHolder();
    servletHandler.addFilter(guiceFilterHolder,
        createFilterMapping("/*", guiceFilterHolder));

    FilterHolder strutsFilterHolder = createStrutsFilterHolder();
    servletHandler.addFilter(strutsFilterHolder,
        createFilterMapping("/*", strutsFilterHolder));    

    return servletHandler;
  }

  private FilterHolder createGuiceFilterHolder() {
    FilterHolder filterHolder = new FilterHolder(GuiceFilter.class);
    filterHolder.setName("guice");
    return filterHolder;
  }

  private FilterHolder createStrutsFilterHolder() {
    FilterHolder filterHolder
        = new FilterHolder(StrutsPrepareAndExecuteFilter.class);
    filterHolder.setName("struts2");
    filterHolder.setInitParameter("struts.devMode", "true");
    return filterHolder;
  }

  private FilterMapping createFilterMapping(
      String pathSpec, FilterHolder filterHolder) {
    FilterMapping filterMapping = new FilterMapping();
    filterMapping.setPathSpec(pathSpec);
    filterMapping.setFilterName(filterHolder.getName());
    return filterMapping;
  }

  public void run() throws Exception {
    server.start();
    server.join();
  }

  private String getBaseUrl() {
    URL webInfUrl = WebServer.class.getClassLoader().getResource("WEB-INF");
    String webInfUrlString = webInfUrl.toExternalForm();
    return webInfUrlString.substring(0, webInfUrlString.lastIndexOf('/') + 1);
  }

  public static void main(String[] args) throws Exception {
    WebServer server = new WebServer();
    server.run();
  }

}

This web app used the Struts 2 filter and the Guice filter.  However, we specified them in code instead of in the web.xml.  We hardcoded struts.devMode to true, but you can easily see how we could make it true or false at runtime whereas that is impossible using a web.xml file.

You can also run Tomcat in embedded mode.

Creating .asc signature files with GPG

08/01/2010

First make sure you don’t have a key already:

gpg --list-keys

If you didn’t and need to create a key then run:

gpg --gen-key

It might hang for awhile while generating enough random entropy. Run “ls -R /” to speed things up.

And upload it to a public key server:

gpg --keyserver hkp://pgp.mit.edu --send-keys <keyid>

Now list the keys again to get the keyid:

gpg --list-keys

The keyid is the half after the / in:

pub   XXXX/XXXXXXXX 2011-12-05

Then generate your key:

gpg -ab <filename>

If you’re doing this for an upload to the Maven repositories, you’ll need to do this for each of the four file (.jar, -sources.jar, -javadoc.jar, and .pom) and then jar all eight files together in a bundle.jar file.  More details available on Maven’s how to generate PGP signatures page.

Getting started with R

07/25/2010

Getting Help

R is incredibly frustrating to learn because it is impossible to do a Google search and have anything meaningful come back for the query “R”.   RSeek may provide some help in this regard.

Installing Libraries

To use R in Linux, I recommend installing the latest version of the RKWard GUI program.

As an example here we’ll display a stock chart using the quantmod library.  To install a library add yourself to the staff group (sudo usermod -a -G staff ${USER}) run install.packages:

install.packages("Defaults")
install.packages("quantstrat", repos="http://R-Forge.R-project.org", type="source")
install.packages("PerformanceAnalytics", repos="http://R-Forge.R-project.org", type="source")

In the code above c is used to combine arguments into a list and is a very common R command.  You’ll also notice the use of repos to specify a named argument.

You can install packages from source if needed:

install.packages("xtime", lib="/home/bmccann/R/i486-pc-linux-gnu-library/2.10", repos = NULL, type="source")
install.packages("xts", lib="/home/bmccann/R/i486-pc-linux-gnu-library/2.10", repos = NULL, type="source")

You can also update packages as needed:

update.packages()

In order to load any libraries that you’ve installed, you’ll need to run library:

# load the quantmod library
library(quantmod)
library(TTR)
library(blotter)
library(PerformanceAnalytics)
library(FinancialInstrument)

# get the S&P 500 data from Yahoo!
getSymbols("^GSPC", from = "1900-01-01", to = Sys.Date())

# chart the past 5 years of the S&P 500 with 50-day SMA
chartSeries(GSPC, TA="addSMA(n = 50)", subset='last 5 years', theme='white')

# chart the past 5 years of the S&P 500 with 200 and 300 day SMA
sma200<-SMA(close, n=200)
sma300<-SMA(close, n=300)
chartSeries(close, subset='last 5 years', theme='white')
addTA(sma200, on = 1, col=c('red','red'))
addTA(sma300, on = 1, col=c('blue','blue'))

# 50-day SMA in a more manual fashion to demonstrate adding custom lines to chart
close<-Cl(GSPC)
sma<-SMA(close, n=50)
chartSeries(close, subset='last 5 years', theme='white')
addTA(sma, on = 1, col=c('red','red'))

# Reset the workspace
rm(list=ls(all=TRUE, pos=.blotter), pos=.blotter)
rm(list=ls(all=TRUE, pos=.instrument), pos=.instrument)

If you get a message about a public key the next time you run “sudo apt-get update“:

W: GPG error: http://cran.stat.ucla.edu lucid/ Release: The following signatures couldn't be verified because the public key is not available: NO_PUBKEY D67FC6EAE2A11821

Then you should run:

gpg --keyserver keyserver.ubuntu.com --recv D67FC6EAE2A11821
gpg --export --armor D67FC6EAE2A11821 | sudo apt-key add -

Performance Problems

You may notice that performance is harder to get right in R.  The standard for-loop solutions used in other languages are very inefficient in R and should be vectorized.  This Stack Overflow discussion gives some insight into R performance problems.  You can time you code by surrounding it with system.time:

time <- system.time({
  # code here
})
print(paste("The code took", time["elapsed"], "seconds."))

Testing

RUnit is helpful in testing R code.  I wrote an RUnit test suite for blotter, which may be a helpful example.

Installing Evan’s Debugger in Ubuntu

06/27/2010

Evan’s Debugger is a Linux replacement for OllyDbg.

You can install it by downloading the .tar.gz and doing the following:

$ sudo apt-get install libqt4-dev
$ sudo apt-get install libboost1.40-all-dev
$ tar zxvf debugger-0.9.15.tgz
$ mv debugger /usr/local/src/
$ cd /usr/local/src/debugger
$ qmake -makefile DEFAULT_PLUGIN_PATH="/usr/lib/edb/"
$ make
$ sudo make INSTALL_ROOT=/usr install

My first experience with Ubuntu

06/26/2010

I just got a laptop loaded with Lucid Lynx and have had a bit of a mixed experience adjusting.  I’ve actually used Ubuntu a bit in the past, but only minimally and never as my primary computer until now.

First reactions

  • I like the default background.
  • Have the fonts improved?  Fonts have always looked bad on Linux distros I’ve used in the past, but the Ubuntu font seems to be pretty clear.
  • Why is the window close button in the top left?  Every computer I’ve ever used it’s been in the top right.  I hate that its anywhere else in Ubuntu.  It’s annoying because it goes against convention.  It’s also frustrating because it’s not uniform.  E.g. when closing tabs or windows in Chrome, the x is still in the top right.
  • OMG.  Why is it so hard to change anything on the menu bar?  To move anything I have to right click every single icon on the menu bar and uncheck “Lock to Panel”.  Then I need to specifically select the Move option to be able to move the icon.  It’s very annoying that this is so difficult.  A much better UI would be a global lock/unlock for the panel instead of the per-icon mechanism and drag and drop support without having to first go into move mode.
  • Finally!!!  You fixed the menus!!  The menus in every other Linux distro I’ve ever used have been super cluttered and unorganized.  I LOVE that they don’t suck anymore.  Do not underestimate how important this is.
  • The menus themselves are even harder to change than the menu bar.  I had to do a Google search to figure it out.  Who was the genius that decided you need to go to System > Preferences > Main Menu?  Why the hell can’t I just drag icons and around and right click icons to edit their properties?

Nice surprises

  • The pop up that appears when you change the volume or connect to Wi-Fi is beautiful and super friendly.  This is the one place where usability is hands down better than XP!  The volume bars in XP were really ugly.  And I hated having to x out of the Wi-Fi connection pop-up in XP.  The Ubuntu one nicely fades out after a second or so.  Kudos to that UI designer.  Can he be in charge of the rest of the UI?
  • Wow does the Wi-Fi connect fast after startup
  • Making Windows+L lock the screen on my computer was surprisingly easy.  The Keyboard Shortcuts window itself was really difficult to use, but I was really happy how easy it was to find.
  • Hulu Desktop is a savior.  It kept me from defenestrating my computer when the website was totally broken in Linux.
  • I was able to use KeePass 2.x eventhough it’s a Windows program.  I just needed to install libmono-system-runtime2.0-cil, libmono-winforms2.0-cil, and xdotool.  No I can type “mono KeyPass.exe” to run the program.  Awesome!

Frustrations

  • Why does the volume control come with so much other crap?!!! It was on a panel that had a ton of garbage on it, so I took it off and it’s very difficult to get it back without a all the other junk.
  • Can’t play DVDs after first installing.  I understand there are license restrictions, so it might not be feasible to install by default, but they should make it easier for people who want to utilize the full functionality of their machines.  E.g. on first run there should be a wizard asking if you want to install the ability to play DVDs.  And if you try to play a DVD, instead of just giving up it should tell you that you need to install libdvdcss2.
  • The active window is shown as being lighter in the bottom panel than the others.  This is confusing as all hell, so I recommend using the Radiance theme.
  • Using NX shadowing requires disabling Compiz.
  • It seems that by default there is no GUI installed for controlling the firewall in Ubuntu?  Can that really be true?
  • There are completely different panel buttons for logging out and shutting down.  These two buttons/menus should be merged into one.
  • It’d be nice if I didn’t have to install an extension to make backspace work in Chrome.
  • I wanted to see what Kubuntu was like so I installed KDE.  I’ve always preferred KDE in the past, but it was just awful on Ubuntu.  The menus were so cluttered I didn’t know where to go for anything.  When I switched back to Gnome now all of my menus were now cluttered there too with a bunch of KDE crap!  I uninstalled the KDE Plasma Desktop library that I checked to install KDE, but it left all of it’s dependencies (i.e. everything).  It was quite an ordeal to uninstall.  I uninstalled a couple of the base libraries and that got most the garbage off my system.

Nagging throw my chair through the window frustrations

  • Please, please, please make Ctrl+Y redo in gedit.  Redo is Ctrl+Y in every other program I use in Ubuntu (Eclipse, Gimp, Chrome, Firefox, Open Office, Scribes, Geany, etc).  If you want to keep Ctrl+Shift+Z as redo that’s fine, just add a second key binding for Ctrl+Y.  I might have to finally plunk down the money to try the new Linux version of UltraEdit.
  • The battery life stinks compared to Windows.  I’m using a Lenovo T400, which had XP on it previously and the battery life was phenomenal.  Now’s it’s abysmal.  If I leave my machine in my bad in hibernate mode for a day the battery will have died.
  • Ubuntu has managed to take Flash on Linux to a whole new low.  It works worse than on any other Linux distribution I’ve ever used, which is saying a lot.  I realize it’s not totally their fault and hope that this will become a non issue with WebM, but right now it’s an enormous frustration.

Necessary fixes

  • Put the x, minimize, and maximize buttons back in the top right corner of the windows.  Big thanks to gdi2k for pointing out a solution in the comments.  I first tried to fix this by changing to a different theme, which solved the problem, but made everything super ugly.
  • Get rid of the pointless envelope in the top right corner. Run sudo apt-get purge indicator-messages, right click the envelope and choose “Remove From Panel”, and then “Add to Pannel…” followed by “Indicator Applet”
  • Get a text editor where Ctrl+Y works.  Download scribes or run sudo apt-get install geany and then change the default text editor.
  • Install libdvdcss2 so that you can watch DVDs.
  • Install nautilus-open-terminal so that you can open a terminal from Nautilus (the file explorer)

Optional customizations

  • Install the Conky system monitor: sudo apt-get install conky and put a configuration in ~/.conkyrc
  • Install Java: sudo apt-get install openjdk-6-jdk
  • Remove the games: sudo apt-get purge gnome-games-common

Stay current

  • Optional.  If you’d like the latest stable software instead of the long term support version then select: System > Administration > Software Sources > Updates > Release upgrade > Normal releases.

Installing Google products

  • sudo gedit /etc/apt/sources.list
  • Add “deb http://dl.google.com/linux/deb/ stable non-free main” and “deb http://dl.google.com/linux/deb/ testing non-free main”
  • sudo apt-get update
  • Install picasa, googleearth, google-chrome-stable, or google-desktop-linux via the Ubuntu Software Center

Security and remote desktop

Overall I rather like Ubuntu.  OpenSUSE 11.2 left me feeling rather frustrated, so I’ve now switched to Ubuntu on my home machine as well.

Hibernate with JPA Annotations and Guice

05/01/2010

In this tutorial, I use the H2 database, which you can utilize by downloading the jar or you can replace with your own DB.

First off, you need to create a persistence.xml in a folder named META-INF at the root of your classpath. For example, if you’re using Maven you can create src/main/java/META-INF/persistence.xml. It lists all the classes you want Hibernate to persist and any other Hibernate properties you might want to specify. I also define Hibernate properties later on in the tutorial when creating the EntityManagerFactory.

<persistence xmlns="http://java.sun.com/xml/ns/persistence"
             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd"
             version="2.0">
  <persistence-unit name="db-manager">
    <class>com.benmccann.db.ExamplePersistedClass</class>
    <properties>
      <!-- Disable the second-level cache  -->
      <property name="hibernate.cache.provider_class" value="org.hibernate.cache.NoCacheProvider"/>

      <!-- Default is false for backwards compatibility.  Should be used on all new projects -->
      <property name="hibernate.id.new_generator_mappings" value="true"/>
    </properties>
  </persistence-unit>
</persistence>

We listed the class com.benmccann.db.ExamplePersistedClass as being the only persisted class, so now we’ll go ahead and create it. Note that you need a no-argument constructor. Fields in your bean will be persisted unless annotated with @Transient. More info about persisted classes is available in the Hibernate documentation.

package com.benmccann.db;

import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;

@Entity
public class ExamplePersistedClass {

  @Id
  @GeneratedValue
  private Long id;
  
  private String otherField;

  public ExamplePersistedClass() {}

  public void setId(Long id) {
    this.id = id;
  }

  public Long getId() {
    return id;
  }

  public void setOtherField(String otherField) {
    this.otherField = otherField;
  }

  public String getOtherField() {
    return otherField;
  }

}

And we’ll create a DAO for it:

package com.benmccann.db;

import javax.persistence.EntityManager;

public class ExamplePersistedClassDao {

  protected EntityManager entityManager;
  
  @Inject
  public ExamplePersistedClassDao(EntityManager entityManager) {
    this.entityManager = entityManager;
  }
  
  public void saveInNewTransaction(ExamplePersistedClass object) {
    entityManager.getTransaction().begin();
    save(object);
    entityManager.getTransaction().commit();
  }
  
  public void save(ExamplePersistedClass object) {
    entityManager.persist(object);
  }
  
  public ExamplePersistedClass getByOtherField(String otherField) {
    return (ExamplePersistedClass) entityManager
        .createQuery("select e from ExamplePersistedClass e where e.otherField=:otherField")
        .setParameter("otherField", otherField)
        .getSingleResult();
  }

}

And finally, we’ll create a Guice module to define the injection. Note that EntityManagerFactory is thread-safe while EntityManager is not. I use ThreadLocal storage here in order to have one entity manager per thread. When creating the EntityManagerFactory notice that I use the same “db-manager” string that is defined in the persistence.xml file. Also, I defined most of my Hibernate properties here rather than in the persistence.xml file to demonstrate how you can alter the values of these properties. For example, when writing tests it could be very helpful to override the connection string to point to a local test database.

package com.benmccann.db;

import java.util.HashMap;
import java.util.Map;

import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;

import com.google.inject.AbstractModule;
import com.google.inject.Provides;
import com.google.inject.Singleton;

/**
 * @author Ben McCann (benmccann.com)
 */
public class DbModule extends AbstractModule {

  private static final ThreadLocal<EntityManager> ENTITY_MANAGER_CACHE
      = new ThreadLocal<EntityManager>();

  public void configure() {
  }

  @Provides @Singleton
  public EntityManagerFactory provideEntityManagerFactory() {
    Map<String, String> properties = new HashMap<String, String>();
    properties.put("hibernate.connection.driver_class", "org.h2.Driver");
    properties.put("hibernate.connection.url", "jdbc:h2:test");
    properties.put("hibernate.connection.username", "sa");
    properties.put("hibernate.connection.password", "");
    properties.put("hibernate.connection.pool_size", "1");
    properties.put("hibernate.dialect", "org.hibernate.dialect.H2Dialect");
    properties.put("hibernate.hbm2ddl.auto", "create");
    return Persistence.createEntityManagerFactory("db-manager", properties);
  }
  
  @Provides
  public EntityManager provideEntityManager(EntityManagerFactory entityManagerFactory) {
    EntityManager entityManager = ENTITY_MANAGER_CACHE.get();
    if (entityManager == null) {
      ENTITY_MANAGER_CACHE.set(entityManager = entityManagerFactory.createEntityManager());
    }
    return entityManager;
  }

}

Now we can run our code:

package com.benmccann.db;

import java.sql.SQLException;
import java.util.Date;

import org.junit.Assert;
import org.junit.Test;

import com.google.inject.Guice;
import com.google.inject.Injector;
import com.benmccann.db.DbModule;
import com.benmccann.db.ExamplePersistedClass;
import com.benmccann.db.ExamplePersistedClassDao;

public class H2DBTest {

  @Test
  public void testDb() throws SQLException {
    Injector injector = Guice.createInjector(new DbModule());
    ExamplePersistedClassDao examplePersistedClassDao = injector.getInstance(ExamplePersistedClassDao.class);   

    ExamplePersistedClass example = new ExamplePersistedClass();
    example.setOtherField("hello world");
    examplePersistedClassDao .saveInNewTransaction(quote);

    ExamplePersistedClass retrieved = examplePersistedClassDao.getByOtherField("hello world");

    Assert.assertEquals(example.getId(), retrieved.getId());
    Assert.assertEquals(example.getOtherField(), retrieved.getOtherField());
  }

}

Trouble Resuming NX Session

03/17/2010

Resume button disabled

I was unable to resume my NX session.  While trying to connect, the resume button was greyed out (or grayed out)  This apparently can happen if the two machines are running at a different color depth.

The machine I was trying to connect to was running Ubuntu, so I checked the color depth (sudo cat /etc/X11/xorg.conf) and saw that it was running at 24 bit.  Then I checked the color depth on my Windows machine (Control Panel > Display > Settings > Color Quality) and saw it was running at 16 bit.  There was no option to set it to 24-bit, so I chose the option “Highest (32 bit)”.  No more disabled resume button!

I think the cause of the problem was plugging my laptop into the projector at work yesterday.  It apparently changed my color depth and Windows didn’t reset it when I exited presentation mode.

Execution of last command failed

Trying to reconnect to my NX session kept failing.  I hit the Details button and saw the following:

NX> 596 NX> 596 ERROR: NXNODE Ver. 3.4.0-6  (Error id e76DC5C)
NX> 596 NX> 596 ERROR: resume session: run commands
NX> 596 NX> 596 ERROR: execution of last command failed
NX> 596 NX> 596 last command: '/bin/kill -USR2 16905'
NX> 596 NX> 596 exit value: 1
NX> 596 NX> 596 stdout:
NX> 596 NX> 596 stderr: /bin/kill: 16905: No such process

The only thing I found that would let me connect to my box via NX at all was to “rm /usr/NX/var/db/running/*” in order to kill my current session.  Killing the session is a sucky option, but at least now I can use NX again.

Using Struts 2 on Google App Engine

12/20/2009

Google App Engine (GAE) has some great benefits such as scalability and the fact that it’s free to start.  When using Struts 2 with Google App Engine there a few things to keep in mind.

The first is that it runs inside a security sandbox that is more restrictive than your typical Java environment.  This means that OGNL, the expression language that Struts 2 uses, will not work correctly out of the box.  You can fix this by adding a listener as described in this article.  An example listener can be found here and is used in this web.xml file.

The second problem is that Google App Engine has some special URLs that it uses.  If you try to visit them, Struts 2 will attempt to process the request as if it’s a Struts 2 Action and will bomb out when the Action can’t be found.  You can add an exclusion filter to your struts.xml to counteract this problem:

<constant name="struts.action.excludePattern" value="/_ah/.*"/>



Newer Posts
Older Posts