Friday, April 1, 2011

Building and Deploying OpenMRS from the Code Base

This blog post deals with building and deploying the OpenMRS codebase. Please note that for this example I'm using SpringSource Tool Suite as my IDE.

The first step is to create a new workspace and then get the OpenMRS code. the steps for doing this are outlined at https://wiki.openmrs.org/display/docs/Step+by+Step+Installation+for+Developers

The next thing you'll need to do is right click on the pom.xml within the openmrs project and select "Run As" --> "Maven Install"

It took about a minute for everything to build on my machine, but once it was all done I was left within a WAR file on my local hard drive. For me it was located at: C:\Users\jeremy\Documents\OpenMRS\openmrs\webapp\target\openmrs.war Please note that you'll need to "refresh" you workspace in order for it to show up in your Project Explorer tree.

The next step is to take the openmrs.war file and place it in the webapps folder within your tomcat install or for me in the customized tomcat instance provided by SpringSource. Once you either start up or restart your tomcat instance you should see a new folder in the webapps folder of your tomcat install that is called 'openmrs'.

You'll then need to go to http://localhost:8080/openmrs/index.htm

At that point you'll see a screen that asks if you want to populate the MySQL database with test data or if you want to start from scratch. Either way you'll need to provide the root password for your MySQL database so that it can be configured properly for OpenMRS.

If you choose to let OpenMRS create the test data for you then you'll next see a screen that lists 4 or 5 tasks each of which have a progress bar. I believe it took about 5 minutes for my machine to churn through everything on that page. Once that step is all done then you should see the following screen:


At that point you should be able to use the default user name / password (admin / Admin123) to check out the application. NOTE: Usually the default is admin / test, but something with this installation process changes that up.

Sunday, March 13, 2011

Getting Started With Open States -- Fun with GitHub and Public Keys

A couple months back I started to hear about a great project called Open States whose goal is to scrape data from web sites of each state within the union so that the information could be shared more easily. I really wanted to get involved with this project but there were a couple issues:
  1. Project used python (don't know it)
  2. Project hosted on GitHub (haven't used it)
  3. All of the supporting documentation was for linux users (I can use Linux as a general office worker... using it as a development platform is beyond me at the moment)
Even with all of those issues I still wanted to get involved so I read a couple books on python programming,  reviewed the code base, and tried to figure out what it meant to be a Git user along with doing development on Linux.  I started off with their Contribution Guide and read the getting Getting Started on GitHub.  Then I tried to get my environment setup.  After installing Git and the python dependencies pointed out in the Contribution Guide I tried to clone my forked version of the openstates repository and that is where the fun began.

I was supposed to be able to run the following command from the shell in order to get the code downloaded to my computer.

git clone git@github.com:jwmajors81/openstates.git

However, I ran into two issues.

  1. My account within Linux didn't have permission to update the known_hosts file (/home/jeremy/.ssh/known_hosts
  2. I got a permission denied message from GitHub... the exact message was "Permission denied (publickey)"

After looking at the SSH Troubleshooting guide on GitHub I realized that I skipped a couple steps in my setup.... however fixing that issue was a little harder than I would have wished. I ended up resolving the issue by running all git and ssh commands using SUDO. I know that isn't the most ideal way to do this, but I just couldn't figure out how to give my user id (jeremy) access to the /home/jeremy/.ssh/ directory. I'm sure if I would have looked into it more I would have found the solution (chmod is your friend), but I simply didn't want to deal with it at the moment. So I did the following:

  1. Executed sudo ssh-keygen -t rsa "{email address}" and at all of the prompts I just hit enter to accept defaults. This populated the /root/.ssh/id_rsa.pub file with a key
  2. Copied key generated in id_rsa.pub file to Account Settings in GitHub. Look at step 4 on http://help.github.com/linux-set-up-git/ for more information
  3. Executed sudo ssh git@github.com to make sure that everything was setup. If you get permission denied then that means that you didn't do something correctly :(
    1. you can use the command sudo ssh -v git@github.com to get more verbose messages about the failure. If you don't see "Offering public key: /root/.ssh/id_rsa" in the debug messages then that means you don't have any public keys ready to offer.

At that point I was able to execute sudo git clone git@github.com:jwmajors81/openstates.git and finally the forked code was on my machine. Time for a beer.

Thursday, January 13, 2011

Glassfish Admin Console -- Problem Loading Page

Today I installed Glassfish v3 and when I tried to go to the administrative console all I went get would be a message stating that the admin console was initializing and then it would just show a gray bar at the top with a blue background.   At the same time I found the following log within my server.log file (D:\glassfish\glassfishv3\glassfish\domains\domain1\logs\server.log)

[#|2011-01-13T12:14:44.036-0600|INFO|glassfish3.0.1|javax.enterprise.system.std.com.sun.enterprise.v3.services.impl|_ThreadID=27;_ThreadName=Thread-1;|Cannot refresh Catalog : Connection timed out: connect|#]


It turns out that the admin console tries to call out to the internet on startup and ends up timing out when it cannot get to the internet.  For those of us who work for companies that implemented proxies this can be a bit problematic.  Luckily after doing some searching online I found some links that helped me solve the problem.  The most useful was from Stackoverflow which provided the solution (run
./asadmin create-jvm-options -Dcom.sun.enterprise.tools.admingui.NO_NETWORK=true). 

Please note that the asadmin file can be found within the bin directory of your root Glassfish installation path. 

The Stackoverflow link is: http://serverfault.com/questions/103780/how-to-stop-openesb-glassfish-admin-console-from-opening-connection-to-glassfish
I also was able to find a bug that discussed the problem (http://java.net/jira/browse/GLASSFISH-11057).

Monday, August 2, 2010

Updating Existing Applications via WebSphere Administrative Console (Simple Update)

The purpose of this entry is to provide fellow developers where I work a quick review of how you can deploy an application using the WebSphere Administrative Console. The first step is to bring up the WebSphere Administrative Console using SSL, which can be accessed by going to https://{serverName}:9043/ibm/console, where you replace {serverName} with a dns entry or the IP address of the websphere server. When security is enabled for the console, you will be prompted to enter your user name and password.

Once the home page is displayed you will need to click on "Applications" on the left hand menu and then "Enterprise Applications" which will be displayed after you click on "Applications."

A new screen will be displayed which lists all of the current applications installed on that server, which may actually include applications that are deployed websphere instances on that server (NOTE: A single physical websphere instance can have more than one logical websphere server instances installed on it). To see all of the logical server instances on the box you will click on "Servers" on the left hand navigation pane and then click on "Application Servers."

On the "Enterprise Application" screen you will click on the Checkbox next to the project name you are updating then click on the "Stop" button at the top of the datagrid.

Once the application is stopped you will click on the check mark next to its name again and then click on the "Update" button.

On the "Preparing for the application installation" page you will
  • "Replace the Entire Application" and upload the new EAR file."
  • Select "Prompt me only when additional information is required"
  • Click "Next"
On the next screen you do not need to change any of the settings, just accept the default and click "Next"

Click "Finish" so that the installation actually begins

The screen will then present console output until the installation is complete and then you'll be able to "Save Master Configuration" which will end up taking you back to the "Enterprise Applications" screen.  (NOTE:  If you are working in a clustered environment, then you will want to click on "Rollout Update")

You will need to click on the check mark next to the application you just installed and then click on the "Start" button.

If the application starts successfully you will be presented with a message stating so.  If it does not then you will want to look at the websphere log files which will be in a location like:


\\{physical server name}\e$\WebSphere\AppServer\Profiles\AppSrv\logs\{logical websphere server name}\


If trace is enabled then you will be able to check out the trace.log file to see the error.  If not then the SystemErr.log file will have the error message.

Tuesday, June 22, 2010

Using String.format to easily output arguments like .NET or C++ allows

When I started programming using Java I was surprised when I didn't find an equivalent to the functionality provided by String.format in .NET (or similar functions in C++) which allowed you easily to mix string output and variables without having to deal with manually concatenating the data which to me always makes the code look very very ugly. For example, if you wanted to output the arguments passed to a function in .NET then you could do something like the following

function doSomething(arg1 as String, arg2 as String, arg3 as string) as Object
    logger.finest("Arguments passed are arg1: {0} arg2: {1} arg3: {3}", arg1, arg2, arg3)
    ...
    ...
end function

If we executed the above function as follows:

doSomething("foo", "bar", "donkey")

then the output would be:

Arguments passed are arg1 foo arg2 bar arg3 donkey

To me this solution helps to minimize the compexity of the code and just looks pretty.

In java traditionaly I would traditionally have implemented the same functionality as follows:

function Object doSomething(arg1 as String, arg2 as String, arg3 as string){
    logger.finest("Arguments passed are arg1: " + arg1 + " arg2: " + arg2 + " arg3: " + arg3);
    ...
    ...
}

Besides always having to deal with eclipse trying to insert extra " characters it just looks ugly (especially if you are opening the file in something that doesn't do syntax highlighting.

Thankfully today I discovered that as of Java 1.5 the String.format function does provide the same functionality as .NET (joy)

The code can now be written as:

function Object doSomething(arg1 as String, arg2 as String, arg3 as string){
    logger.finest("Arguments passed are arg1: %s arg2: %s arg3: %s", arg1, arg2, arg3);
    ...
    ...
}

Now doesn't that just look beautiful.

More information can be found at: http://www.rgagnon.com/javadetails/java-0463.html

Friday, April 30, 2010

Delayed environment variable expansion in Windows

Today I got to learn the wonders of "Delayed Environment Variable Expansion" in windows.... this one really hurt my head :)

As a basis for this entry I'm going to use information from another article as the starting point (http://stackoverflow.com/questions/305605/weird-scope-issue-in-bat-file). After I read the article for the first time I still wasn't sure what was going on so I'm going to explain in a little more detail below.

For the example we'll start with the code below:

set VAR=before
if "%VAR%" == "before" (
set VAR=after
if "%VAR%" == "after" @echo If you see this, it worked
)

When I first looked at the code I throught that I would see "If you see this, it worked" in the command prompt window when the code is ran, but unfrotunately that is not how bat files work... (this really surprised me).

What is really happening is as follows:

1) Windows loads "before" into the variable
2) Windows loads the entire if into memory
3) Windows sets all instances of %VAR% to before
4) when the code hits the following line "if "%VAR%" == "after" @echo If you see this, it worked" the value in %VAR% is "before" because the value was replaced prior to the "set VAR=after" statement and %VAR% will only be equal to "after" once the program exits the if statement's scope

To take this example one step further I added "@Echo %VAR%" at the end of the code (after the if statement) as described below.

set VAR=before
if "%VAR%" == "before" (
set VAR=after
if "%VAR%" == "after" @echo If you see this, it worked
)
@Echo %VAR%


When the code above executes you get the following output to the command window:

if "before" == "before" (
set VAR=after
if "before" == "after"
)
after

Please note that once the program gets out of the if statement scope the value in %VAR% IS set to "after".


From the articles I've read thus far the system works like this because this is how it was originally implemented. However, there is something called "delayed environment variable expansion" in windows that makes the command file work as we expect. The code with delayed environment variable expansion implemented is provided below:

SETLOCAL EnableDelayedExpansion
set VAR=before
if "%VAR%" == "before" (
set VAR=after
if "!VAR!" == "after" @echo If you see this, it worked
)
@Echo %VAR%


The most important difference with the code provided above is the statement "SETLOCAL EnableDelayedExpansion". When this is set all variables marked with '!' instead of '%' are evaluated at runtime when they are used rather than when the block of code they are in is evaluated.

So with that being said, when the code above is executed you'll get the following output.

set VAR=after
if "!VAR!" == "after"
)
If you see this, it worked
after