Home » Devtech review » LangsNTechs » Java » OpenJPA » 1.0.1 » ElasticPath migrations and related quirks

ElasticPath migrations and related quirks

Hello dear readers!
It’s been a long time since I planned to start blogging about ElasticPath, and actually a long time since I blogged about anything at all. So today is the day! But, since it’s the very first time, the post may not be that much about ElasticPath itself but more about some “quirks” in technologies used inside it, that we faced during various migrations. But don’t worry, you won’t be disappointed – it’s all still very very relevant. So, let’s go!

ElasticPath
If  you’re not familiar with this product I guess the first thing you might think after reading post header is “Elastic what?” (-:
Well, let’s familiarize quickly with ElasticPath (EP for short) and what it is about.

Full name: ElasticPath e-commerce platform
Address: www.elasticpath.com
Latest stable version: 6.2.2
Siblings: BEA AquaLogic Commerce Services (EP 5.1, 6.0)
Purpose: E-commerce platform, i.e. solution for creating, configuring, customizing and running web-shops.
Technologies: Java, Spring IoC, Spring MVC, Spring Security, OpenJPA + Spring AOP-powered declarative transactions (and thus AspectJ), Spring Remoting, Apache SOLR (and thus Apache Lucene), JAX-WS, JAI, Eclipse RCP, Drools, Tuckey URL-Rewrite filter, Apache Velocity, DWR (and also common miscellaneous libs like Quartz, Stringtemplate, Log4j, different Apache commons etc).
Requirements: JDK1.5/1.6 + JAI 1.1.3 or later, servlet container (tested+documented deployment onto Tomcat, JBoss, BEA/Oracle Weblogic and IBM WebSphere), RDBMS (tested+documented+scripts provided for MS SQL Server 2005, MySQL 5.x, Oracle 10g/11g, Apache Derby).
Documentation: official, freely available, rich and elaborate (from video-lessons and webinars for manager to in-depth technical information and API JavaDocs for developers and system administrators).
Important standouts: Source code open for customers that acquired product license. Community for developer of customer companies (known as ElasticPath Grep Community).
Overall impression: finally an e-Commerce done right! Though still somewhat raw at few points (ehm… done, right? (((-: )

Having a more detailed overview of ElasticPath and it’s stand-outs and features will require a separate post (or even several posts), so that will be all for now as for familiarizing. But this should be enough for newcomers to have the general understanding on what we’re dealing with here, I suppose.

A little bit of history
“From the past come the storms”. Our initial acquaintance with ElasticPath was somewhat indirect – we started to work with it’s “ugly brother” BEA AquaLogic Commerce Services, or ALCS for short. The differences between EP and ALCS were rather not in favor for latest: Java packages renamed from com.elasticpath.** to com.bea.alcs.**, source code for all but Storefront not available, “tight coupling” with WebLogic server (so no Tomcat or JBoss), no working build scripts but half-broken integration with BEA Workshop/Workspace, and the only constructive difference (which anyway caused us more trouble than benefit in the end) – integration with WebLogic security realms for customer registration. ALCS had versions 5.1 and 6.0, which correspond to 5.1.x and 6.0.2/6.0.3 versions of EP. In year 2009 ALCS was discontinued, so 6.0 was the last released version.

Let’s start with two boring stories about ALCS (-: , and then continue to more interesting stuff.

ALCS to EP DB migration and Drools rules
We’ve been working with ALCS 6.0, and at a certain point decided to switch to ElasticPath in order to obtain source code for “missing parts” and eventually upgrade to EP 6.1.2 (which was the latest EP version at that moment). So we had to migrate our database with products and stuff from ALCS6.0 to EP6.1.2. ElasticPath provides migration scripts, which worked well for us, but one problem remained – promotion rules, that for some reason are stored in DB in some binary representation (why, EP team, oh why?)
It seems that due to package name change from com.bea.alcs.** to com.elasticpath.** the rules could no longer be deserialized from their binary representation that was stored in DB, because Java classes with corresponding fully qualified names didn’t exist anymore (as they were renamed from com.bea.alcs.**.Something to com.elasticpath.**.Something). The exception that occurred on deserializing was preventing application from starting. This was of-course a problem we wanted to fix ASAP.
Since we only had a couple of promotion rules defined, it really was faster to re-create them anew than to try to somehow fix the binary representation of unknown format that was in DB, so our solution for this was simple: “delete from TRULESTORAGE”.
The problem might never occur for people that haven’t “met ALCS”, but it’s better to be aware of what monsters live in TRULESTORAGE DB table.

ALCS to ALCS DB migration and User accounts
Another ALCS problem story is about accounts for users registered in Shop.
Due to abovementioned integration of ALCS registration with WebLogic security realms, simple export-import of Shop DB from one environment to another didn’t work for user accounts. The information about them was still stored in Shop DB, but no longer in WebLogic domain. Thus user could not log in or even use “forgot password” function because he couldn’t be authenticated on WebLogic side, and registering new user with “used” email address also didn’t work – email address was rejected as occupied already on ALCS side. Stalemate!
There were two obvious ways to fix this: either migrate user data stored in WebLogic domain (and thus have user accounts working again), or delete user info from EP DB (and thus have all accounts removed).
During our “relationship” with ALCS at different times we did it one way or another, depending on the circumstances.

MS SQL Driver and OpenJPA: “JDBC” is not a number!
To run ElasticPath6.1.2 itself or it’s data population scripts with Microsoft SQL Server 2005 you have to use proper JDBC driver. Or else…
Don’t know about later versions, but the verison of OpenJPA that EP6.1.2 comes with (which is version 1.0.1+some EP patches) has a really strange code in it. Like:

...
this.platform = "Microsoft SQL Server";
...
if (driverName.indexOf(this.platform) != -1) {
String versionString = driverName.substring(this.platform.length() + 1);

if (versionString.indexOf(" ") != -1) {
versionString = versionString.substring(0, versionString.indexOf(" "));
}
int version = Integer.parseInt(versionString);
if (version >= 2005) {
this.supportsXMLColumn = true;
}
}

The driverName is obtained from JDBC Driver class, so for Microsoft SQL Server 2005 driver it’s supposed to be something like “Microsoft SQL Server 2005 JDBC Driver 1.2”. But if you were unlucky to try “not appropriate” version of JDBC driver for MS SQL, you would get a lengthy exception stacktrace, starting from something incomprehensible like

Error creating bean with name 'java.util.HashSet#7448bc3d' defined in ServletContext resource [/WEB-INF/conf/spring/service/serviceCM.xml]: Cannot resolve reference to bean 'messageSourceCache' while setting constructor argument with key [1]; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'messageSourceCache' defined in ServletContext resource [/WEB-INF/conf/spring/views/velocity/velocity.xml]: Invocation of init method failed; nested exception is  org.apache.renamed.openjpa.persistence.PersistenceException: For input string: "JDBC"
	at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveInnerBean(BeanDefinitionValueResolver.java:230)

and on digging down revealing the true cause (which is still incomprehensible until you take a look at the OpenJPA source code snippet provided above):

Caused by: java.lang.NumberFormatException: For input string: "JDBC"
	at java.lang.NumberFormatException.forInputString(NumberFormatException.java:48)
	at java.lang.Integer.parseInt(Integer.java:449)
	at java.lang.Integer.parseInt(Integer.java:499)
	at org.apache.renamed.openjpa.jdbc.sql.SQLServerDictionary.connectedConfiguration(SQLServerDictionary.java:92)
	at org.apache.renamed.openjpa.jdbc.sql.DBDictionaryFactory.newDBDictionary(DBDictionaryFactory.java:158)

The driver probably returns something like “Microsoft SQL Server JDBC Driver …” as it’s name, so parsing “JDBC” as number fails with exception of-course. Naturally, parsing version number from driver name is something rather strange to do. But even if there is a good reason for this, still guys, couldn’t you just put try/catch around this Integer.parseInt and leave this.supportsXMLColumn as false on exception? Arrggg.

I can’t tell now which was the “wrong” version of JDBC driver (maybe it was one for MS SQL 2000, which than can be considered as our mistake, as EP docs state that MS SQL 2005 is required), but I can tell you that Microsoft SQL Server 2005 JDBC Driver 1.2 is the right version. So if you have this problem – go for it and download MS JDBC driver ver.1.2 for MS SQL 2005.

EP6.1.2 and Java6
This is a known issue with Java6, and it’s mentioned in EP guides, but still two of our people (me and SA on customer side) ran into this problem independently at different time, so it seems to be worth mentioning once more: the “-Dsun.lang.ClassLoader.allowArraySyntax=true” JVM parameter has to be used for JDK/JRE6, or else…

<openjpa-1.0.1-ep-6.1-2-rsvnversion: invalid option:  fatal user error> org.apache.renamed.openjpa.persistence.ArgumentException: There was an error invoking the factory for field "com.elasticpath.
domain.rules.impl.EpRuleBaseImpl.ruleBase" on datastore value "[B@3de74140": com.elasticpath.domain.EpDomainException: Fatal error reading rule base
        at org.apache.renamed.openjpa.meta.FieldMetaData.getFieldValue(FieldMetaData.java:1314)
        at org.apache.renamed.openjpa.kernel.StateManagerImpl.store(StateManagerImpl.java:764)
        at org.apache.renamed.openjpa.jdbc.meta.strats.HandlerFieldStrategy.load(HandlerFieldStrategy.java:174)
        at org.apache.renamed.openjpa.jdbc.meta.FieldMapping.load(FieldMapping.java:796)
        at org.apache.renamed.openjpa.jdbc.kernel.JDBCStoreManager.load(JDBCStoreManager.java:833)

This exception is kind-of fooling for those who know about rules deserialization problem mentioned above – it seems to be somehow related to it. And in a way it is, because again the class can not be found here, but deleting rules from DB wouldn’t work, and here is the reason for it:

Caused by: java.lang.ClassNotFoundException: [Lorg.drools.spi.FieldConstraint;

That’s what root cause ClassNotFoundException exception look like. Obviously “[Lorg.drools.spi.FieldConstraint” is not a proper fully qualified class name because of “[L” array prefix. So don’t rush to delete stored promotion rules, but if you’re on Java6 use the abovementioned JVM parameter and it should fix your problem.

EP-logue
Ok, that’ll be all for now. Hope this post will save someone a couple of hours (or maybe even days) of problem investigation.

And a little teaser: next post about ElasticPath will be about how to hack it to overcome a certain limitation in it’s storefront – to allow browsing store catalog products without specifying a category or keyword. This might be very interesting for some people (-:

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s