Monday, May 12, 2008

creating a WebObjects application with Maven: WOProject, WOCreator, and WOLips


I'm starting a project working with WebObjects. I'm most familiar with
Tomcat, J2EE standards, and Ant/Maven, so let's see what it takes to get a working application.

WOCreator

A friend found posts referencing a different project WOCreator, and this one turned out to be very easy to install. Just follow the instructions on their main page. Here's what I ended up using (though I believe the 'repository' flag is wrong, but I suspect it's not being used in my case).


mvn com.bbc.newsi.mvn.plugins:maven-wocreator-plugin:create-project \
-DgroupId=com.icentris.webdynamics -DprojectName=sampleCreator \
-Drepository=file:///home/trent/.m2/repository -DwebObjectsVersion=5.4


The one difficulty I had was with all the jars. First of all, you have to get the WebObjects jars into your repository; they provide a script that will install all the required jars into your local repository. This is incredibly helpful. Second, you have to manually install the following jars if you don't already have them; a quick web search will tell you where you can get them:
  • com.sun.jdmk jmxtools 1.2.1
  • com.sun.jmx jmxri 1.2.1
  • javax.jms jms 1.1
Quite frankly, after the struggles with WOProject, this is an awesome tool because it just works: you run the Maven tasks 'create-project', then 'package', then 'jetty:run-war'. The only thing that hung me up for a minute was the URL; Jetty started up and reported that I could go to the following URL:

http://trent-laptop/sampleCreator-application-1.0-SNAPSHOT/WebObjects/sampleCreator-application-1.0-SNAPSHOT.woa

However, this was wrong; I had to add the right port and change the context to the name I gave to 'create-project':

http://trent-laptop:8080/sampleCreator/WebObjects/sampleCreator-application-1.0-SNAPSHOT.woa

Wonderful! I have an application that I was able to tweak with 'webobject' tags and see something work. It only took about 24 hours because I started with WOProject first (see below). But start with WOCreator and you'll be working in no time.


WOProject bootstrap

It looks like the WOProject will install the jars and set up a sample app with Maven.

At first, I can't get the bootstrap to work:

[INFO] The plugin 'org.apache.maven.plugins:maven-wobootstrap-plugin' does not exist or no valid version could be found


I really struggled with this plugin stuff. The thing that finally seemed to get it to at least recognize the 'mdimension' repository was to create a dummy pom.xml and then add the plugin info to the 'reporting' section of a pom:


<plugins>
...
<plugin>
<groupid>org.objectstyle.woproject.maven2</groupid>
<artifactid>maven-wobootstrap-plugin</artifactid>
</plugin>
...
</plugins>


I then had to add the POM file directly to my local repo copy (to get around it's inability to find the org.apache.commons.lib.SystemUtil class):


http://webobjects.mdimension.com/maven2/releases/org/objectstyle/woproject/maven2/maven-wobootstrap-plugin/2.0.14/maven-wobootstrap-plugin-2.0.14.pom


... and I finally got something to work. Here's the final command:

mvn org.objectstyle.woproject.maven2:maven-wobootstrap-plugin:install \
-DwebObjectsLibFolder=/usr/local/apple/Library/WebObjects/lib -DwebObjectsVersion=5.4


That's frustrating, because I'm not quite sure what piece I added that made it all work. I spend about 6 hours fooling around with this stuff. Maybe I'll try and figure out this plugin craziness sometime.

Right now, I want to see if I can get the archetype setup to work.



WOProject archetype

I start with the following default from their example:

mvn archetype:generate -DarchetypeCatalog=local


It promps me to choose:

Choose archetype:
1: local -> woapplication-archetype (WebObjects Application Archetype)
Choose a number: (1):


... but the first time I got this error:

org.apache.maven.archetype.downloader.DownloadNotFoundException: Requested download does not exist.


Fine. So I try this, but it's totally wrong because it dies before I can even choose:

mvn org.objectstyle.woproject.maven2:archetype:generate \
-DarchetypeCatalog=local


And I graduate to a "FATAL ERROR" with this attempt:

mvn org.objectstyle.woproject.maven2:woapplication-archetype:generate \
-DarchetypeCatalog=local


At this point, I choose the first one again, and it seems to work because it prompts me for more and starts making the project. Argh! Is that good now that something's working, or bad because I have no idea what fixed it?

BTW, if you get the following error, make sure there's no pom.xml in the current directory:

[ERROR] org.apache.maven.archetype.exception.InvalidPackaging: Unable to add module to the current project as it is not of packaging type 'pom'


I learned I have to specify the "WebObjectsVersion" because it defaults to something else and doesn't ask you the first time around. (You could also answer "n" at the end of the other questions so that it prompts you for it, but then you have to answer all the questions again.) While I'm at it, I might as well specify it all.

So here's the final command:

mvn archetype:generate -DarchetypeCatalog=local -DWebObjectsVersion=5.4 \
-DgroupId=icentris-webdynamics -DartifactId=sample -Dversion=0.1 -Dpackage=app

Although this creates a basic app, the app doesn't build correctly with 'mvn package'. I tried a few things but it cannot find a properties file (that exists), and it says to run another buildfile (that doesn't exist):

org.objectstyle.woenvironment.env.WOBuildPropertiesNotFoundException: Could not find wobuild.properties. Run the buildfile: woproperties.xml first.

I've given up on this set of tools for now, mostly because I've found something else that works.


WOLips

I have to mention WOLips: it claims to be "the toolset that Apple itself uses internally"; it certainly has great documentation (which I used to help with WOCreator above), and a colleague has successfully started porting his Mac-based development environment to WOLips so that the rest of us can play with it. Unfortunately, I followed their instructions to install with Eclipse Update Manager and I ended up with a project that has a bunch of errors and a directory structure that doesn't match their screen shots (and their proposed fixes don't remedy the situation). Well, that was a dead-end, but at least it was a quick one!

Update: I've got WOLips working, and fairly easily. I don't know what I did, but I erased all my earlier stuff and started with a new WO Application and I got something without any errors, and something that ran great when I right-clicked on Application.java and choose "Run As" a "WOApplication. This generates some build files for an Ant build process as well. If you have to work with a WebObjects application, I've heard that the UI is essential so you really have to use WOLips.

Thursday, May 8, 2008

installing FrontBase on Ubuntu (and/or Debian)

I got a grundle of problems attempting to install FrontBase, but my flailing attempts finally worked, so here's what happened.

Start with the official guide at the FrontBase site.

On my first 'dpkg' attempt, I got the following errors:


$ sudo dpkg -i FrontBase-4.2.8.deb
(Reading database ... 122351 files and directories currently installed.)
Preparing to replace frontbase 4.2.8-1 (using FrontBase-4.2.8.deb) ...
Unpacking replacement frontbase ...
dpkg: dependency problems prevent configuration of frontbase:
frontbase depends on libncurses4 (>= 4.2-3.1); however:
Package libncurses4 is not installed.
frontbase depends on libreadline4 (>= 4.1); however:
Package libreadline4 is not installed.
dpkg: error processing frontbase (--install):
dependency problems - leaving unconfigured
Errors were encountered while processing:
frontbase



Then I tried 'apt-get' and still got errors:


$ sudo apt-get install -f
Reading package lists... Done
Building dependency tree
Reading state information... Done
Correcting dependencies... Done
The following extra packages will be installed:
libncurses4 libreadline4
The following NEW packages will be installed:
libncurses4 libreadline4
0 upgraded, 2 newly installed, 0 to remove and 18 not upgraded.
1 not fully installed or removed.
Need to get 298kB of archives.
After unpacking 709kB of additional disk space will be used.
Do you want to continue [Y/n]? y
Get:1 http://us.archive.ubuntu.com gutsy/universe libncurses4 4.2-10.1 [194kB]
Get:2 http://us.archive.ubuntu.com edgy/universe libreadline4 4.3-18 [104kB]
Fetched 298kB in 2s (131kB/s)
Selecting previously deselected package libncurses4.
(Reading database ... 122351 files and directories currently installed.)
Unpacking libncurses4 (from .../libncurses4_4.2-10.1_i386.deb) ...
Selecting previously deselected package libreadline4.
Unpacking libreadline4 (from .../libreadline4_4.3-18_i386.deb) ...
Setting up libncurses4 (4.2-10.1) ...

Setting up libreadline4 (4.3-18) ...

Setting up frontbase (4.2.8-1) ...
Starting FrontBase service

Processing triggers for libc6 ...
ldconfig deferred processing now taking place




Well, it looks like something happened, so I tried 'dpkg' again and got something a bit different:


$ sudo dpkg -i FrontBase-4.2.8.deb
(Reading database ... 122374 files and directories currently installed.)
Preparing to replace frontbase 4.2.8-1 (using FrontBase-4.2.8.deb) ...
Shutting down FrontBase service
/var/lib/dpkg/info/frontbase.prerm: 11: /etc/init.d/FBWeb: not found
dpkg: warning - old pre-removal script returned error exit status 127
dpkg - trying script from the new package instead ...
/var/lib/dpkg/tmp.ci/prerm: 11: /etc/init.d/FBWeb: not found
dpkg: error processing FrontBase-4.2.8.deb (--install):
subprocess new pre-removal script returned error exit status 127
Starting FrontBase service
Errors were encountered while processing:
FrontBase-4.2.8.deb



Even though it still complains of errors, I tried looking at my processes, and viola:


$ ps -edalf | grep FrontBase
0 S root 24174 1 0 75 0 - 1335 - 13:09 pts/4 00:00:00 /usr/lib/FrontBase/bin/FBExec -autostart




Then I ran through the example statements on the install page via sql92 and saw the first DB running:


$ ps -edalf | grep FrontBase
0 S root 24174 1 0 75 0 - 1335 - 13:09 pts/4 00:00:00 /usr/lib/FrontBase/bin/FBExec -autostart
0 S root 24248 1 0 75 0 - 4392 - 13:13 pts/4 00:00:00 /usr/lib/FrontBase/bin/FrontBase /usr/lib/FrontBase/Databases/firstdb.fb



Great! Now I can even connect with my Java SQL tool using the FrontBase driver with the following info:
  • URL: jdbc:FrontBase://localhost/firstdb
  • User: test
  • Pass:

Wednesday, April 23, 2008

is_ascii Oracle function


Here is an Oracle function that tells whether a column is all ASCII (from Mark Stafford):

create or replace function is_ascii (v varchar2) return varchar2 as
r boolean := false;
begin
r := length(v)
- length(
translate(v
, chr(1)
|| translate(v, chr(1) || ' !"#$%&''()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~', chr(1) )
, chr(1)
)
) = 0;
if v is null then r := true; end if;
if r = true then return 'y'; else return 'n'; end if;
exception
when others then
return null;
end;
/

Friday, April 4, 2008

working with FrontBase

I'm accustomed to working with Oracle, but I'm using FrontBase for a project. So here's some interesting info I've had to learn:

  • Here's a timestamp statement:
update client set enrollment_date = TIMESTAMP '2008-04-03 10:58:30' where client_id = 1000019

  • This sets it to the current time:
update client set enrollment_date = cast(CURRENT_TIMESTAMP as timestamp) where client_id = 1000019

  • Don't try to put numbers inside single-quotes. It will give error 217.

  • To drop a table, add CASCADE at the end:
drop table CLIENT_ADMIN_AUDIT cascade

  • Here are a bunch of error codes you can get back (found here and duplicated on many internet sites):

22 => DB_ERROR_SYNTAX,
85 => DB_ERROR_ALREADY_EXISTS,
108 => DB_ERROR_SYNTAX,
116 => DB_ERROR_NOSUCHTABLE,
124 => DB_ERROR_VALUE_COUNT_ON_ROW,
215 => DB_ERROR_NOSUCHFIELD,
217 => DB_ERROR_INVALID_NUMBER,
226 => DB_ERROR_NOSUCHFIELD,
231 => DB_ERROR_INVALID,
239 => DB_ERROR_TRUNCATED,
251 => DB_ERROR_SYNTAX,
266 => DB_ERROR_NOT_FOUND,
357 => DB_ERROR_CONSTRAINT_NOT_NULL,
358 => DB_ERROR_CONSTRAINT,
360 => DB_ERROR_CONSTRAINT,
361 = "Integrity constraint violation (FOREIGN_KEY...)" (from Java experiments)


  • I keep hitting problems trying to use any native sequence functionality with Hibernate. You get the next sequence number with "SELECT UNIQUE" on the table name, thus:

    select unique from admin_user


    This is automatically available for any table that you create.

    Now, the generic Hibernate JDBC dialect acts badly, so I changed things so that I have to retrieve this unique value every time I try to insert into the DB. Sometimes it was difficult to figure out that this was the problem; even P6Spy wasn't showing me why I was getting an error 116 "DB_ERROR_NOSUCHTABLE". I finally found this statement in the FrontBase logs:


    select next_hi from hibernate_unique_key;


Saturday, March 15, 2008

software to generate genealogy web pages

Our family organization is looking at ways to put our genealogy records and histories online for public view, so I'm looking at our options. Our genealogy records are stored in GEDCOM, so we need to be able to upload that; we want everyone to be able to browse the data without signing up or other complications; we have our own website, so we can generate the content from software and publish it ourselves if necessary; we don't mind spending some money if it'll give us good features for sharing.

Here are my comparisons. I looked at these main features; I'll only mention below if they do NOT have these features.

- access: Does it allow public access without signups or paying?
- reports: Does it have multiple kinds of output?
- map: Does it show a map? (This isn't critical, but it's an indicator of advanced reports.)
- search: Does it allow people to search online?
- history: Does it allow for publishing stories and pictures?


All of these import the Gedcom format, which is critical for us.

Desktop Software

There are many desktop applications that generate reports, so we could use them to take our info and output our web site. They do much the same thing, and they do well in all areas except: they don't have online maps (except GedHTree), and they don't set up great web searches, though they generate many links for things like surname searches to find the person you want.

Personal Ancestral File (look for download link) is the original program, it'll always be around (and free) and we currently use it to maintain our genealogy, but we're not impressed by the pages it generates.

These 3 seem to be at the top because they're comprehensive... so they do more than we need, but they'll import GedCom and generate what we want:

Here's a page that reviews these first three (and a few others).

Master Genealogist - $34-70
... and for the online work add Second Site - $30
I didn't find a comprehensive list of features, but supposedly this is the best; there are companion products offered for things like maps and mobile devices.

Roots Magic - $30
Feature list

Legacy - $35-60
Feature list, and their own comparison with other programs


These 3 were also recommended simply for generating web content:

GedHTree - $20
This one does do maps (and "map sequences" which look interesting). We downloaded and used this successfully; the pedigree charts are nice. It only handles up to about 30,000 names.

GedPage - $10
"Uses Family Group Sheet format." The pedigree chart is simplistic and text-based. You can try it for free (and it processed 120,000-person GEDCOM), but it doesn't generate the pedigree charts.

GED2WEB - $21
Has pedigree charts. Free download trial.


Ged-Gen - $15
Does not create pedigree (or map); reportedly doesn't include photos so those must be done separately. Allows lots of look and feel customization. Free download trial.

GED2HTML - Free
No pedigree charts.




Internet Services

Tribal pages - $0

This does well in all areas except: there are no histories; it seems to only do the relationships. For a good example of reports and maps, see this record: http://dee894500.tribalpages.com/tribe/browse?userid=dee894500&view=0&pid=1648&rand=626605690

Roots Web - $0
This does well except that there aren't many reports and it doesn't do the histories.


Ancestry.com - $13-30/month
This appears to do great in all areas except: it doesn't allow full access unless you sign up. It claims to allow access to existing information for free, so I even attempted to sign up to see someone's historical info, but the page just offered the paid memberships (with 14-day trial). I definitely don't want to use this to try and share with people!

As a side note: I've heard from sources in the LDS Church that their new version of familysearch.org will have more options for attaching notes to individuals, and it should be available worldwide by 2009 (maybe even sometime this year).

Friday, March 14, 2008

maven 2 deploy-file command

I can never remember the vagaries of the deployment URL, etc!

Here is an example for activation.jar in our "soa" repository. Make sure to have the username/password for "soa-repo" in settings.xml, and probably the distributionManagement.repository in the pom.xml.


mvn deploy:deploy-file -DgroupId=javax.activation -DartifactId=activation -Dversion=1.0.2 \
-Dpackaging=jar -Dfile=/home/trent/dl/jaf-1.0.2/activation.jar \
-DrepositoryId=soa-repo \
-Durl=scp://soa@soa.dev.hq.icentris/home/soa/tomcat/webapps/ROOT/repository2

Oracle and JDBC test from different timezones

I predicted that Java would send the right thing to Oracle and we'd see the same thing in the database. I was wrong and Vijay was right: Oracle ends up with a different value, even though we send the exact same java.util.Date value.

Following is our test where we point Java programs running in different timezones to the same Oracle database.

Here are our two runs of the program below, from UT and then LA timezones:



$ java -cp .:ojdbc-14_g.jar DateTest UT
UT Pi Time Los_Angeles: 1205533140000 = Fri Mar 14 16:19:00 MDT 2008
UT SQL Pi Time Los_Angeles: 1205533140000 = 2008-03-14 16:19:00.0

$ java -cp .:ojdbc-14_g.jar DateTest LA
LA Pi Time Los_Angeles: 1205533140000 = Fri Mar 14 15:19:00 PDT 2008
LA SQL Pi Time Los_Angeles: 1205533140000 = 2008-03-14 15:19:00.0



Here are the results we find in the database when the dust settles:

UT piTimeLos_Angeles 2008-03-14 16:19:00.0
LA piTimeLos_Angeles 2008-03-14 15:19:00.0


DateTest.java:




import java.util.*;
import java.sql.*;
import java.text.*;


/**

create table time_test (
name varchar2(100),
time date
)

*/
public class DateTest {
public static void main(String[] args) {
String outPrefix = "";
if (args.length > 0) {
outPrefix = args[0];
}

Connection conn = null;
PreparedStatement pstat = null;
try {
SimpleDateFormat formatter = new SimpleDateFormat("yyyy/MM/dd HH:mm");
TimeZone timezone = TimeZone.getTimeZone("America/Los_Angeles");
formatter.setTimeZone(timezone);
java.util.Date piTimeLos_Angeles = formatter.parse("2008/03/14 15:19");
System.out.println(outPrefix + " Pi Time Los_Angeles: " + piTimeLos_Angeles.getTime() + " = " + piTimeLos_Angeles);

String DRIVER = "oracle.jdbc.driver.OracleDriver";
String URL = "...";
String USERNAME = "...";
String PASSWORD = "...";
Class.forName(DRIVER);

conn = DriverManager.getConnection(URL, USERNAME, PASSWORD);
pstat = conn.prepareStatement("insert into time_test (name, time) values (?, ?)");

//java.sql.Date piTimeLos_AngelesSql = new java.sql.Date(piTimeLos_Angeles.getTime());
java.sql.Timestamp piTimeLos_AngelesSql = new java.sql.Timestamp(piTimeLos_Angeles.getTime());
System.out.println(outPrefix + " SQL Pi Time Los_Angeles: " + piTimeLos_AngelesSql.getTime() + " = " + piTimeLos_AngelesSql);

pstat.setString(1, outPrefix + " piTimeLos_Angeles");
//pstat.setDate(2, piTimeLos_AngelesSql);
pstat.setTimestamp(2, piTimeLos_AngelesSql);
pstat.executeUpdate();

pstat.close();
conn.close();

} catch (Exception e) {
e.printStackTrace();
}
}
}