Looking for software experts?
Need an expert advice on software development? Need consulting work done in time and at high standards? Tremend has the right solution for you.

We can provide expertise in:
  •    » high traffic and complex content website infrastructures using Java, PHP or .NET. More here ...
  •    » mobile applications for iPhone, Android or J2ME. More here ...

For an enquiry, send an email to contact [at] tremend [dot] ro.

Create and populate your database independent of the db server using ant, dbunit and hibernate

January 31st, 2007 by Martin Paraschiv in Java, General

    Database creation is such a common task that you must have some scripts and tips and tricks at hand, in order to have it done as quickly as possible. What about when there’s more than one type of RDBMS in your project that you need to handle. Things get a little messy.
     How about using just one XML file and two or three libraries, regardless of the RDBMS type. Wouldn’t that be cool?
     I’m saying, all you need is ant, dbunit and Hibernate as libraries and a couple of files for data and database connection configuration. With this you’ll be able to populate with only one file init-dataset.xml different rdbms like Oracle, MySql, MsSql, Postgres. For a complete list of supported rdbms have a look at dbunit SupportedRDBMS
Database creation and population process is in four steps:
    1.Create an ant build.xml file and setup a project with path for used libraries
    2.Generate DDL from Hibernate mapping
    3.Create database schema running generated DDL
    4.With DBUnit populate database created above, providing as input a seed XML file with data you’re database must be populated with.

    1.
     <project name=”OMS” basedir=”.” default=”deploy-reload-classes”>
         <property file=”web/WEB-INF/classes/db.properties“/>
         <property name=”ddl.file” value=”ddl.sql”/>
         <property name=”lib.dir” value=”lib”/>

         …

         <path id=”project.classpath”>
         <fileset dir=”${lib.dir}”>
         <include name=”**/*.jar”/>
         </fileset>
         </path>

         <!– dbnunit task definition –>
         <taskdef name=”dbunit”
         classname=”org.dbunit.ant.DbUnitTask”
         classpathref=”project.classpath”/>

         </project>

Typical ant project setup. In order to use dbunit task we need to define it.

     2.
     <target name=”hbm2ddl-schema” description=”Generate DDL from Hibernate mapping”     depends=”build”>
         <java classname=”net.sf.hibernate.tool.hbm2ddl.SchemaExport” fork=”true”>

         <!– Hibernate Properties –>
         <jvmarg value=”-Dhibernate.dialect=${databaseDialect}”/>

         <!– Mapping Files –>
         <arg value=”ObjectModel.hbm.xml”/>

         …

         <classpath refid=”project.classpath”/>

         </java>
     </target>

These lines should be familiar to an hibernate user.

     3.
     <target name=”sql-run-ddl” description=”Run DDL script” depends=”hbm2ddl- schema”>
         <sql url=”${databaseURL}” driver=”${databaseDriver}”
         userid=”${databaseUser}” password=”${databasePassword}”
         onerror=”continue” autocommit=”true” print=”yes”>
         <classpath refid=”project.classpath”/>
         <transaction src=”${ddl.file}”/>
         </sql>
     </target>

all database related variables should be defined into a properties file, I called it db.properties, see step 1.

     4.
     <target name=”dbunit-init-db” description=”using dbunit for testing” depends=”sql-run-ddl”>
         <dbunit driver=”${databaseDriver}”
         url=”${databaseURL}”
         userid=”${databaseUser}”
         password=”${databasePassword}”>
         <operation type=”DELETE”
         src=”db/defaults/init-dataset.xml”/>
         <operation type=”INSERT” format=”flat”
         src=”db/defaults/init-dataset.xml”/>
         </dbunit>
     </target>

after initializing database we can populate it.

     For a simple database setup the script above should do it.
     But sometimes we need to initialize more complex databases, where we have some foreign key circular dependency.

Some Tips & Tricks

     Unfortunately dbunit is not perfect, meaning it has some bugs. One is that it doesn’t handle too well circular reference between tables, and second is when a db is initialized. At initialization operation, in the seed dataset file each new row for each new table must have all fields populated, otherwise unpopulated fields (from first row, but populated in subsequent rows) will be set to null;
     Here are some workarounds.
    1.instead of using a row with missing column, use one with complete columns.
    For example:
     using

         <dataset>
             <user ID=’1′ />
             <user ID=’2′ NAME=’user name’/>
         </dataset>

     will insert null in all NAME columns of user table. The solution is to use

     <dataset>
         <user ID=’2′ NAME=’user name’ />
         <user ID=’1′ />
     </dataset>

    1.instead of using INSERT operation, use REFRESH operation.At REFRESH operation, data of existing rows are updated and non-existing rows get inserted. For clean initalization, perform CLEAN before.

     <dataset>
         <user ID=’1′ col2=’val1′/>
         <user ID=’2′ NAME=’user name’ col2=’val2′/>
         <!– if met twice id=2, than the second time it means there’s an update –>
         <user ID=’2′ NAME=’user name’ />
     </dataset>

    In the update part you must update only fields that you know they were setup to null.
    The second method is also useful when you need to populate a db with data that contains circular reference. Let’s suppose we have users and portfolios. And for some reason we would like to have a reference of an portfolio into user’s table, and a reference of user into portfolio table. The data will look something like this:

     <dataset>
         <user ID=’1′ name=’default user’ portfolio_id=’1′ />
         <portfolio ID=’1′ user_id=’1′ name=”default portfolio”/>
</dataset>

     If we’ll use the dataset above with INSERT operation, dbunit will report an error, that portfolio with id=1 doesn’t exists.

    Using REFRESH operation, with an appropriate dataset the problems will disappear.

     <dataset>
         <user ID=’1′ name=’default user’ />
         <portfolio ID=’1′ user_id=’1′ name=”default portfolio”/>
         <!– if met twice id=2, than the second time it means there’s an update –>
         <user ID=’2′ NAME=’user name’ portfolio_id=’1′/>
     </dataset>

     As you can see portfolio_id is missing from the first row. So dbunit gets fooled. Next record will be inserted with reference to user table. And the last record will update reference of user record to portfolio record.

    The bottom line: in spite of it’s imperfections, dbunit has reached 2.2 version after more than one year breakend, it can be used very efficiently for other purposes than database testing. A database setup operation independent of RDBMS type can be done easily enough with DBUnit. I hope you find this interpretation useful.

Good luck!

Read the rest of this entry »

read more ...

Cursor disappears in Firefox

January 22nd, 2007 by Marius Hanganu in HTML, Javascript

Firefox has this annoying problem of the cursor caret becoming invisible sometimes. For example, when showing up a div, the textboxes inside that div don’t have the cursor. You can edit them, but you can’t really know where exactly the cursor is. This can be very frustrating when editing texts in input boxes.

The mouse doesn’t actually dissapear, as one friend cleverly noticed. If you move your div around, you’ll find it blinking somewhere underneath. This has nothing to do whatsoever with z-index, but with div’s scrolling as some people point out .

So basically, to make your caret visible, you’d have to replace your div’s style from something like:

overflow: auto

to

overflow: hidden;



This helped me get rid of the invisible cursor problem. I guess other overflow values will work as well, except for auto.

br />

technorati tags:, , , , , ,

read more ...

My experience with web services with Spring, Axis, XFire

January 22nd, 2007 by spostelnicu in Java, General, Spring

First thing to note is that, this being my first contact with web services (SOAP and WSDL), it took me quite a lot of time (almost five working days) to learn about the technologies involved and try to implement and publish a web service in my application.

Of these four and a half working days (36 hours), about 14 cumulated hours were spent stepping through the library code, trying to determine the causes for various errors (especially for XFire, which returned all sorts of cryptic and unhelping error messages).

1) First try: Apache Axis

The first day was dedicated to learning about Axis and trying what it can do.

The second day was dedicated to writing and testing the necessary configurations to publish my specific service, which contained many service methods and serializable classes.

My opinion after this short experience is this: the setting up of the service with Axis seems to be too complicated for my simple needs.

After writing the service interface, you have to run two tools: Java2WSDL and WSDL2Java. The first one will generate the WSDL for the web service. The second one will generate auxilliary classes: remote interface, client stub, service locator helper – all of them hard-coded for my service.

Of course, to integrate them into a build process you have to learn to use the ant tasks for Java2WSDL and WSDL2Java, and after the code generation, compile the generated files.

And then you have to take care of the deployment of the service by using the generated deployment.xml, and I didn’t quite understand how to automate the deployment (the documentation was not very clear about this).

All I needed was some kind of generic Java class to expose web services by proxying SOAP calls to a Spring managed bean that implemented my interface. Something like: WebServiceFactory.create(MyServiceInterface.class).

I didn’t want no WSDL or XMLSchema or namespaces or some other messy XML stuff.

And for the client part, something like this was desirable: WebServiceProxyFactory.create(MyServiceInterface.class)

Which, fortunately, I actually found the next day in the form of XFire.

2) Second try: XFire

The third day I decided to switch to XFire, because of its simpler usage (no more WSDL, no more deployment.xml, no more two-steps build with Java2WSDL and WSDL2Java…)

So I tried to learn about services.xml and xfire-servlet.xml and stuff.

The first thing that sticks out is the “not-so-complete” documentation and with the way that XFire just doesn’t like to show useful error messages. Most of the errors are either silently ignored, or replaced by some generic message like “Invalid SOAP request”.

One big problem that I had was that at first I tried to access the XFire service with the Axis client that I already have. Big mistake! After half a day of stepping through the XFire code, I discovered that the problem was that my client was sending a request as RPC/encoded, which XFire does not support. And instead of telling me that, XFire was simply returning a fault with the internal exception message, which was: “ Index: 1, Size: 1 “.

Imagine my frustration! I didn’t have any clue as to what this can mean. Could it have something to do with the SOAP elements? Could it be some internal tables used? Could it mean the index of the method parameters? And, most annoying: is this an ERROR MESSAGE? What is the error? “Index: 1, Size: 1″ – I don’t see any error in here!

Of course searching the web didn’t help me in this case, so I started debugging the XFire service handlers, and learning the XFire insides along the way.

After about an hour I discovered that this was no more than an IndexArrayOutOfBoundsException! It seems I haven’t met one very often in my days, otherwise I could have been able to recognise the error message. But XFire didn’t return in the fault message the name of the exception, it returned just the error message. And no error logging. And of course, do not even dare to ask a stacktrace.

Anyway, eventually I discovered that the exception was caused because the handler wasn’t able to recognise the format of the SOAP request, which contained multiref elements. After googling some more and not finding any reference to multiref and XFire, I eventually found that the multirefs were there because of the RPC/encoded format – which, no need to mention, I had very little knowledge about. Remember, this was my first contact with SOAP, and I wasn’t in the mood to learn all the “subtleties” of the protocol. I just wanted to expose my service with the least effort.

The fourth day I learned how to expose services with XFire by using JSR 181 Annotations. Because of the incomplete documentation and examples, this caused a problem that took me 3 hours to debug and still couldn’t solve until next day: the service class wasn’t accesible through XFire, which just kept returning empty pages (another annoying behaviour: no error message, no 404, no service fault, no “Invalid SOAP request”, no nothing. Just a blank page with the footer “Generated by XFire”)

I couldn’t tell if it was a problem with SimpleUrlMapper, or with Jsr181HandlerMapping, or if I should use DispatcherServlet instead of XFireSpringServlet…

The documentation contained very confusing examples, in which a SimpleUrlMapper had a mapping from “/” to handlerMapping, and handlerMapping was a Jsr181HandlerMapping. My confusion was: what does Jsr181HandlerMapping do? It’s another URL mapper? And if it is, when are the Spring beans initialized?

The next morning I finally discovered the cause for the last problem encountered.

After yet another session of analysing the XFire source code, it was clear for me that Jsr181HandlerMapping was not an URL mapper. Actually, all it did was to call XFire to register my classes that had @WebService annotations. But then again, why didn’t it work?

To configure this part, I followed an example that I found on some blog, because the XFire documentation lacked this part. I actually followed exact steps showed in the example, along with the example classes and settings. And what frustrated me more was that his conclusion was “So we see that setting up web services by using XFire and JSR 181 annotations is a no brainer.” If it is a no brainer, why it doesn’t work ?! :p

But apparently the author of the example forgot to mention that in order for this to work, you have one more thing to configure: to add your bean in applicationContext.xml

In his example this step was missing, so of course the service was not registered, because (as I found out after analysing the XFire source code) Jsr181HandlerMapping checked all the already configured beans to see if they had @WebService annotation.

So in conclusion:

  • XFire is indeed very easy to configure (if you follow a complete example, like this one that I found later), but lacks many “advanced” SOAP features.
  • Axis is more advanced, more configurable and with more advanced SOAP and WSDL features, but a “little” bit more difficult to configure.

technorati tags:, , , , ,

read more ...

Cryptic fault when trying to call an XFire SOAP service using a SOAP client generated with Axis

January 22nd, 2007 by spostelnicu in Java, General

I encountered a problem when trying to call an XFire SOAP service using a SOAP client generated with Axis, and after finding the “solution” I decided to share it with you so you won’t have to repeat my steps.

I’ll be short:

When trying to call an XFire SOAP service using a SOAP client generated with Axis, I get the following (very cryptic) fault:

Index: 1, Size: 1
AxisFault
faultCode: {http://schemas.xmlsoap.org/soap/envelope/}Server
faultSubcode:
faultString: Index: 1, Size: 1
faultActor:
faultNode:
faultDetail:
{http://xml.apache.org/axis/}stackTrace:Index: 1, Size: 1

This is generated by an internal IndexArrayOutOfBoundsException (which I couldn’t determine only after step-by-step debugging through the XFire sources), at line 191 in org.codehaus.xfire.service.binding.AbstractBinding (xfire-distribution-1.2.4-sources.jar):

p = (MessagePartInfo) opInfo.getInputMessage().getMessageParts().get(param);

Basically, the parser is trying to get the next xml element in the request, which doesn’t exist.

When examining the SOAP message, I found this:

<soapenv:Body>
<ns1:myMethod soapenv:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"
xmlns:ns1="urn:MyNamespace">
<in0 href="#id0" />
</ns1:myMethod>
<multiRef id="id0" soapenc:root="0" soapenv:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"
........

So it seems that the request is using RPC encoding, which unfortunately XFire doesn't support.

In conclusion: do not access a service published with XFire with a client generated by Axis, unless you change the default request encoding style from RPC/Encoded to WRAPPED/Literal.

technorati tags:, , , ,