Quantcast
RSS Entries RSS
RSS Subscribe by Email

Security Lockdown for Linux

Automatic updates

If you’re using Ubuntu you can do this by editing /etc/apt/apt.conf.d/50unattended-upgrades. Running out of date packages with security holes is a good way to get your machine pwnd.

Remove unused software

Every piece of software installed on your system provides one more attack point for malicious users. You should inventory your system and remove anything you don’t need. E.g. to remove Ubuntu One from your system:

sudo apt-get purge ubuntuone*

Secure SSH

Edit /etc/ssh/sshd_config:

PermitRootLogin no
AllowUsers bmccann nx gitolite

You may also disable password authentication and replace it with public key authentication:

PasswordAuthentication no
PubkeyAuthentication yes

Restart the SSH daemon:

sudo service ssh restart

or

sudo /etc/init.d/ssh restart

This disallows login via password and instead replaces it with login via public/private key pair. To setup your public key encryption run ssh-keygen on the client and put ~/.ssh/id_rsa.pub from the client into ~/.ssh/authorized_keys on server.

Sometimes while messing around with SSH settings, you’ll lock yourself out. I this case it’s nice to use the -v option with the ssh client.

You can also setup shortcuts in ~/.ssh/config. E.g. the shortcut below turns ssh gitolite into an alias for ssh -l gitolite -p 77777 bensdynamicdns.getmyip.com.

Host gitolite
   User gitolite
   Hostname bensdynamicdns.getmyip.com
   Port 77777
   IdentityFile ~/.ssh/id_rsa

Secure NX

If you’d like to setup NX with this configuration it takes a couple extra steps than a normal NX installation. Note that every additional service you run on the machine provides one more attack point for hackers, so you’re more secure not running NX at all. However, if you choose to run NX for the benefits that it provides then here are some steps to help keep you safe:

  • Download and install the client, node, and server in that order
  • In /etc/ssh/sshd_config add the nx user by setting AllowUsers nx and restart the ssh daemon sudo /etc/init.d/ssh restart.
  • NX uses a deprecated location for the ssh authorized_keys file, so you must fix that or you will get a public key authentication failed error. Open /usr/NX/etc/server.cfg and change #SSHAuthorizedKeys = "authorized_keys2" to SSHAuthorizedKeys = "authorized_keys". Now run sudo mv /usr/NX/home/nx/.ssh/authorized_keys2 /usr/NX/home/nx/.ssh/authorized_keys if there’s an authorized_key2 file present.
  • Run sudo /usr/NX/scripts/setup/nxserver –install
  • If you’ve disabled SSH passwords then you’ll also need to set EnableUserDB = "1" and EnablePasswordDB = "1" in /usr/NX/etc/server.cfg and then run sudo /usr/NX/bin/nxserver –useradd $USER since we’ve disabled passwords when we locked down SSH.
  • Change the default NX key.  Run sudo /usr/NX/bin/nxserver –keygen.  In your NX client, open “Configure…” > “General” tab > “Key …” and copy the contents of “/usr/NX/share/keys/default.id_dsa.key” into the key window and save it.
  • Optional for connecting to multiple servers at once:  Change DisplayBase in /usr/NX/etc/server.cfg.
  • Restart the NX server to pickup your changes: sudo /etc/init.d/nxserver restart

Secure MySQL

Run mysql_secure_installation

Install fail2ban

  • Install fail2ban by running sudo apt-get install fail2ban, which will lockout users who repeatedly try to access your system by guessing passwords.
  • Make your own copy of the configuration file: sudo cp /etc/fail2ban/jail.conf /etc/fail2ban/jail.local
  • Check if fail2ban is running properly: sudo fail2ban-client status

More
Andrew Ault wrote a good article as well.
The NSA has a comprehensive guide to securing a Linux system

Comments (1)

Google GXP Struts 2 Plugin

Google GXP is a replacement for JSP that provides compile-time type safety.  This article is a quick introduction on how to use GXP with Struts 2.
 
1. Download the jar.  It’s not in Maven yet because it’s still unreleased.
 
2. Install the jar in Maven or otherwise put it on your classpath.  You’ll also need the Google GXP jar and the Google Collections jar:
  <dependency>
    <groupId>com.google.gxp</groupId>
    <artifactId>gxp-plugin</artifactId>
    <version>2.2.2-SNAPSHOT</version>
    <scope>system</scope>
    <systemPath>${basedir}/lib/struts2-gxp-plugin-2.2.2-SNAPSHOT.jar</systemPath>
  </dependency>
  <dependency>
    <groupId>com.google.gxp</groupId>
    <artifactId>google-gxp</artifactId>
    <version>0.2.4-beta</version>
  </dependency>
  <dependency>
    <groupId>com.google.collections</groupId>
    <artifactId>google-collections</artifactId>
    <version>1.0</version>
  </dependency>

3. Call the GXP compiler. E.g.

java -cp lib/gxp-0.2.4-beta.jar com.google.gxp.compiler.cli.Gxpc --output_language java com/benmccann/example/web/gxp/*.gxp

4. Add a result type of gxp to your struts.xml:

  <package name="test" extends="gxp-default">
    <action name="TestAction" class="com.benmccann.example.web.action.TestAction">
      <result type="gxp">com/benmccann/example/web/gxp/Index.gxp</result>
    </action>
  </package>

Comments

Commons Math vs. ojAlgo

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.

Comments (7)

MySQL Commands Cheatsheet

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

Allow connections from a remote server:
  • 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;

Comments

Embedded Jetty

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.

Comments (5)

Creating .asc signature files with GPG

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.

Comments (2)

Getting started with R

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.

Comments

Installing Evan’s Debugger in Ubuntu

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

Comments (8)

My first experience with Ubuntu

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.

Comments (11)

Hibernate with JPA Annotations and Guice

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());
  }

}

Comments (9)