Add New Relic in Heroku using Play 2 (Java) Application

Installing New Relic in Heroku using a Play 2.4.x (Java) Application

Hi guys, just wanted to write a small post about installing New Relic on a Play Framework App (version 2.4.x) in Heroku. I struggled a bit with some of the instructions I found through the internet (including Heroku’s and New Relic’s).

What I did to make it work:

Install the New Relic Addon through Heroku’s interface

New Relic Installation Screen

New Relic Installation Screen

This will install the add-on and configure somethings for you (like environment variables). If you do `heroku config` you’l see the following variables:

  • NEW_RELIC_APP_NAME:          APP_NAME
  • NEW_RELIC_LICENSE_KEY:       YOUR_LICENSE_KEY
  • NEW_RELIC_LOG:               stdout

In order for the addon to work you need to enable it’s Java agent, by adding the dependencies to your build.sbt file:

libraryDependencies ++= Seq(

  //Your other dependencies

  “com.newrelic.agent.java” % “newrelic-agent” % “3.25.0”,

   “com.newrelic.agent.java” % “newrelicapi” % “3.25.0”

)

Notice that at the time of writing ( 20/02/2016 – February 20th ) the latest version of the agent is 3.25. You should always check the latest version at maven central and use that.

Now you need the “newrelic.yml” configuration file. You can download when you configure your account in new relic. Once you go to your New Relic account page you’ll see the following screen : Choose “Java”.

new_relic-1After you choose Java, the next screen will show this:

new-relic-3

Click the “Download the Java agent” button. This will download a zip file with the java agent and the newrelic.yml file. My suggestion is copy the newrelic.yml file to the Play Framework’s conf directory ( conf/newrelic.yml ).

Add all the changes to git, and push to heroku.

git add build.sbt

git add conf/newrelic.yml

git commit -m ‘Add new relic addon’

git push heroku master

Now you only to configure the environment variables to run the agent.

heroku config:set JAVA_OPTS=”Xmx334m -Xss512k -XX:+UseCompressedOops -javaagent:target/universal/stage/lib/com.newrelic.agent.java.newrelic-agent-3.25.0.jar -Dnewrelic.config.file=conf/newrelic.yml

Now, I’m not sure if target/universal/stage/lib/com.newrelic.agent.java.newrelic-agent-3.25.0.jar will be the same throughout time, but if you get errors like “cannot open zip file” or “cannot read manifest” I suggest you do the following in your terminal:

heroku run bash

Once inside the web dyno, look around and find where the new-relic jar file is and point the environment variable to it.

Hopefully, that’s all you need. I did encounter other issues, but mostly related by not having the newrelic.yml file in the right place (or not having the configuration pointing to the right place).

Query SQL / BOQL with Dates in where clause using Java

Hi everyone,
One of the things that I struggled in the beginning (a long time ago in a galaxy far away, cof cof) with SQL queries (or BOQL queries if you’re using the XEO framework) was how to make queries using dates in the where clause, something like this:

select * from table where column_date > SOMETHING

Not knowing how to do date comparisons I usually did stuff like this ( evil code ahead, beware ) :

select * from some_table where to_char(column_data,'DD-MON-YYYY') > to_char('23-05-2013','DD-MON-YYYY');

Usually in Java you have java.util.Date instances which I heroically used like the following, in order to be able to create the previous query:

SimpleDateFormat sdf = new SimpleDateFormat("dd-MM-yyyy");
java.util.Date date = loadDateFromSomewhere();
String sql = "select * from some_table where to_char(column_data,'DD-MON-YYYY') > ('"+sdf.format(date)+"','DD-MON-YYYY')";

Well now I don’t do this kind of thing, eh eh… it’s way easier to do such queries using proper data types. Check in a Java SQL Prepared statement:

Connection conn = getConnection();
PreparedStatement statement = conn.prepareStatement("select * from some_table where column_date > ?");
statement.setDate(1, new java.sql.Date(loadDateFromSomewhere().getTime()));

Notice how you pass a java.sql.Date instance (created using the information from the java.util.Date instance) to the parameter. This has the added benefit that no data conversions are done (meaning extra performance). And if you have an index on a date column that index will be used ( I also learned that when you apply a function to an indexed column, that index won’t be used properly as the function has to be applied to every row in the table – check this )

In BOQL by the way it would be like this:

boObjectList.list(getEboContext(), "select Object where column_data > ?", new Object[]{ new java.sql.Date(date.getTime()) });

Important notes:

  • In SQL/BOQL queries you use java.sql.Date and java.sql.Timestamp instances (you don’t use java.util.Date instances)
  • Use java.sql.Date instances when you want to compare Dates only (ignoring time)
  • Use java.sql.Timestamp instances when you want to compare Dates including time information

And voilá… Dates in SQL/BOQL queries (using Java) without much effort. Hope it was useful,  Happy coding!

 

Introducing XALPI – Alternative API for XEO Applications

XALPI

Hi everyone,

I’ve been working on an application, using the XEO Framework, for a while now and there were two situations that I wanted to improve. First it was my inability to write unit tests for my application’s logic (using JUnit, for example) and the other was I had trouble finding which attributes were being used where and overall can’t rely on the compiler to help me out. XEO’s API is very flexible and all but I thought that in order to address these two issues I would have to come up with something on my own.

Notice: This work is not associated with the XEO Framework, although I do work at ITDS (which creates the framework), XALPI does not reflect anything but my own opinion and effort on the subject.

Meet XALPI! (beta)

XALPI stands for XEO ALternative API and is a personal attempt to create a more convenient (for me) API and allow the creation of unit tests. It’s an open source project that you can find on Bitbucket, licensed under the BSD license (rev3), meaning you can do just about anything with it.

You can download it here (see the instructions at the wiki page).

So, what makes XALPI different from XEO’s original API?

  • Provides an interface representing each XEOModel with getters and setters for each attribute (see example bellow)
  • Set iFile values using java.io.File instances
  • Get/Set Lov Values using a class instance (good for searching references) instead of the value itself
  • The description of each attribute/model is placed as javadoc in the generated interfaces / classes
  • Provides an easy API to create lists of objects and iterate a list
  • Provides a new Logger abstraction to allow creating application logic to be tested without needing the XEO Logger (which throws a bunch of errors to the error console when the server is not up and running)
  • Reduces the number of boRuntimeExceptions thrown by the API (only update/destroy throw exceptions)

Each of these situations is (I hope) well explained at the wiki. Although some information may still be missing ( it’s beta after all ) I will, to the best of my abilities, complete it as fast as I can.

An example? Compare the following code (current API) :

public void createHistory(EboContext ctx, BigDecimal patientBoui) throws boRuntimeException {
		Timestamp time = DateUtils.getTodayDateAsTimeStamp();
		long boui = patientBoui.longValue();
        boObjectListBuilder builder = new boObjectListBuilder(ctx, "select FileHistory where user = CTX_PERFORMER_BOUI and file = ? and dateOpen = ?").argsList(boui,time).cache(false);
		boObjectList list = builder.build();
		if (list.getRecordCount() == 0){

			if (logger.isFineEnabled()){
				logger.fine("Created fileHistory for " + patientBoui.longValue());
			}

			boObject historyEntry = boApplication.getDefaultApplication().getObjectManager().createObject(ctx, FileHistory.MODEL_NAME);
			historyEntry.getAttribute(FileHistory.USER).setValueLong(ctx.getBoSession().getPerformerBoui());
			historyEntry.getAttribute(FileHistory.FILE).setValueLong(boui);
			historyEntry.getAttribute(FileHistory.DATE_OPEN).setValueDate(DateUtils.getTodayDate());
			historyEntry.update();
	    } 
	}

With this (XALPI) :

public void createHistory(Patient fileOpened, BaseModel user) throws boRuntimeException{

		Timestamp time = DateUtils.getTodayDateAsTimeStamp();
		FileHistoryList history = Select.FileHistory().where("user = CTX_PERFORMER_BOUI and file = ? and dateOpen = ?").args(fileOpened,time).build();

		if (history.isEmpty()){

			logger.fine("Created fileHitroy for %s",user.getBoui());

			FileHistory history = FileHistoryManager.create();

			history.setDateOpen(DateUtils.getTodayDate());
			history.setFile(fileOpened);
			history.setUser(user);
			history.update();
		}

	}

Check out the rest at the wiki page and tell me if you like it. I’m open to suggestions and improvements

Happy coding!