Saturday, August 14, 2010

Reverse engineering a MySQL schema into JPA classes using AndroMDA

We are looking to use a third party product in our system, and want to integrate our domain with theirs.  I have set up the db schema for the third party in MySQL.  What I am trying to do is create a separate EJB service class to access this third party database.  To do that I want to reverse the database into EJB3 entity classes using AndroMDA.

AndroMDA has an ANT pluging called Schema2XMI which is supposed to automatically generate the domain objects from a schema.  In this post I will attempt to do that.

So far, I have generated a new Andromda project (see previous posts on how to do this).

I have downloaded the AndroMDA binary and exploded it into the folder C:\programs\andromda_bin_exploded
In the root of the new andromda project (same folder as the root pom.xml) I have created the file build.xml and put the following contents inside of it:

           <property name="andromda.lib.dir" value="C:\programs\andromda_bin_exploded\andromda\org\andromda"/>             <property name="andromda.dependency.dir" value="C:\programs\andromda_bin_exploded\lib"/>             <path id="andromda.classpath">         <fileset dir="${andromda.lib.dir}">           <include name="andromda-core/*/andromda-core-*.jar"/>           <include name="andromda-utils/*/andromda-utils-*.jar"/>           <include name="andromda-schema2xmi/*/andromda-schema2xmi-*.jar"/>           <include name="ant/andromda-ant-task/*/andromda-ant-task-*.jar"/>           <include name="metafacades/andromda-metafacades-emf-uml2/*/andromda-metafacades-emf-uml2-*.jar"/>           <include name="metafacades/andromda-metafacades-uml/*/andromda-metafacades-uml-*.jar"/>           <include name="metafacades/andromda-metafacades-uml14/*/andromda-metafacades-uml14-*.jar"/>           <include name="repositories/andromda-repository-emf/*/andromda-repository-emf-*.jar"/>           <include name="repositories/andromda-repository-mdr/*/andromda-repository-mdr*.jar"/>           <include name="repositories/andromda-repository-mdr-uml14/*/andromda-repository-mdr-uml14*.jar"/>           <include name="repositories/andromda-repository-emf-uml2/*/andromda-repository-emf-uml2-*.jar"/>           <include name="translationlibraries/andromda-ocl-query-library/*/andromda-ocl-query-library-*.jar"/>           <include name="translationlibraries/andromda-ocl-translation-core/*/andromda-ocl-translation-core-*.jar"/>           <include name="translationlibraries/andromda-ocl-translation-testsuite/*/andromda-ocl-translation-testsuite-*.jar"/>           <include name="translationlibraries/andromda-ocl-validation-library/*/andromda-ocl-validation-library-*.jar"/>           <include name="templateengines/andromda-templateengine-velocity/*/andromda-templateengine-velocity-*.jar"/>           <include name="cartridges/andromda-java-cartridge/*/andromda-java-cartridge-*.jar"/>         </fileset>         <fileset dir="${andromda.dependency.dir}">           <include name="commons-beanutils/commons-beanutils/*/commons-beanutils-*.jar"/>           <include name="commons-collections/commons-collections/*/commons-collections-*.jar"/>           <include name="commons-digester/commons-digester/*/commons-digester-*.jar"/>           <include name="commons-dbutils/commons-dbutils/*/commons-dbutils-*.jar"/>           <include name="commons-cli/commons-cli/*/commons-cli-*.jar"/>           <include name="commons-lang/commons-lang/*/commons-lang-*.jar"/>           <include name="commons-logging/commons-logging/*/commons-logging-*.jar"/>           <include name="log4j/log4j/*/log4j-*.jar"/>           <include name="velocity/velocity/*/velocity-*.jar"/>           <include name="xerces/xercesImpl/*/xercesImpl-*.jar"/>           <include name="xml-apis/xml-apis/*/xml-apis-*.jar"/>           <include name="jmi/jmi/*/jmi-*.jar"/>           <include name="jmi/jmiuml/*/jmiuml-*.jar"/>           <include name="jmi/mof/*/mof-*.jar"/>           <include name="org/netbeans/mdr/jmiutils/*/jmiutils-*.jar"/>           <include name="org/netbeans/mdr/mdrapi/*/mdrapi-*.jar"/>           <include name="org/netbeans/mdr/nbmdr/*/nbmdr-*.jar"/>           <include name="org/netbeans/mdr/openide-util/*/openide-util-*.jar"/>           <include name="org/eclipse/**/*.jar"/>           <include name="*.jar"/>         </fileset>       </path>       <target name="schema2xmi">         <java classname="org.andromda.schema2xmi.Schema2XMI" fork="true">           <classpath>             <path refid="andromda.classpath"/>           </classpath>           <arg value="-i"/>           <arg value="file:${basedir}/mda/src/uml/schema2xmi/input.xml"/>           <arg value="-u"/>           <arg value="${dbuser}"/>           <arg value="-p"/>           <arg value="${dbpass}"/>           <arg value="-c"/>           <arg value="jdbc:mysql://l127.0.0.1:3306/app"/>           <arg value="-d"/>           <arg value="com.mysql.jdbc.Driver"/>           <arg value="-m"/>           <arg value="file:${basedir}/mda/src/mappings/MySQLMappings.xml"/>           <arg value="-o"/>           <arg value="${basedir}/mda/src/uml/output.xmi"/>           <arg value="-P"/>           <arg value="com::example::app"/>           <arg value="-I"/>           <arg value="Identifier"/>           <arg value="-C"/>           <arg value="Entity"/>           <arg value="-V"/>           <arg value="@andromda.persistence.table"/>           <arg value="-v"/>           <arg value="@andromda.persistence.column"/>         </java>       </target> 

Friday, August 6, 2010

Unit testing EJB3 using JBoss Microcontainer, Andromda generated tests and TestNG

Using Andromda to generate your EJB code, including unit test classes is pretty cool, albeit difficult to get working the first time...   I am currently using Andromda 3.3 since it is the latest released version of Andromda.  It works well once set up initially.

In this post I just want to give a basic overview of how the unit testing works.  It can look very convoluted and can be really difficult to troubleshoot the first time since it may be unclear exactly how it works...

The unit tests are created in the package /core/src/test/java
In this package you will see two files created:  EJB3Container.java and yourClassNameTest.java
The EJB3Container is a common EJB3 container which is set up to use JBoss 3.2.0.ga by default. 
The other class is the test class specific to your service class.  Andromda will generate one of these for each class annotated with the <> stereotype.

Additionally you will see a package /core/src/test/resources which will contain a host of configuration files with various settings that can be changed to affect your unit testing container.  The first two files you will probably be concerned with are the testng.xml file and the embedded-jboss-beans.xml file.

The testng.xml file contains a list of all of the classes that testng will instantiate and inject into the unit testing container.  It is important that testng be configured to use this file, otherwise the andromda test will not work.

The embedded-jboss-beans.xml file contains settings for the connection of the JBoss microcontainer to your local database (amongst other things)... make sure you have this modified appropriately to access your local environment.

The basic flow of the TestNG tests with the andromda build is as follows:

For testing within Eclipse:
TestNG Eclipse Plugin is loaded, it is pointed to the testng.xml file via the configuration screen in Eclipse.  TestNG plugin loads up the EJB3Container and your Test classes.

Your test class is run.  Since the EJB3Container has been previously loaded, your test classes can access the EJB local and/or remote interfaces via JDNI calls to the InitialContext.

Method calls to the EJBs are made in the test class... these get run inside of the EJB3Microcontainer, and the results are returned to the test classes and assertations can be made on them at that point.

Tuesday, August 3, 2010

Unit testing of EJBs using AndroMDA, TestNG and JBoss Microcontainer

I am in the process of trying to get AndroMDA 3.3 running agains the new JBoss Microcontainer and using the latest TestNG version.

Before doing that, I decided to create a new AndroMDA model with a really simple service (one method) one entity with one String attribute and an accompanying ValueObject (again, one String method).



Generated the source using AndroMDA.  This is an EJB3 project, btw.

Right off the bat some things were broken... the generated test class was broken due to changes in the AndroMDA generated 'ServiceLocator'... several method signatures, etc.

Also, testng.jar does not import by default after doing the mvn eclipse:eclipse... I changed the main pom.xml for testng to tell it to include the .jar on compile and I upped testng to the latest verson:


       


I am also using a fresh Eclipse install, so had to install the testNG eclipse plugin to get the tests to run from inside of Eclipse... you can find the plugin install information at:  http://testng.org/doc/eclipse.html


Upon first trying to run the TestNG in debug mode, it did not work.... a little reading on the TestNG site revealed that you need to set up a debug configuration within Eclipse.  To do this, select run--Debug Configurations...

Select TestNG from the list and create a new configuration... in that configuration , under the 'Suite' section, click the browse button and select testng.xml file.  This will inject any classes defined in this xml file whenever TestNG is run... you need the EJB3Container to be injected on each test run.


At this point you can click 'Debug' to attempt to debug your test class.  This will likely fail for you with a runtime exception stating "java.lang.NoSuchMethodError: org.jboss.ejb3.KernelAbstractionFactory.setKernel(Lorg/jboss/kernel/Kernel;)"... a quick search of the Andromda forums revealed that there appears to be conflicting JBoss .jars.

http://forum.andromda.org/viewtopic.php?t=4410&highlight=testng+eclipse

Removal of the duplicate .jars should do the trick...

M2_REPO/org/jboss/jboss-ejb3-client/4.0.5-GA/jboss-ejb3-client-4.0.5-GA.jar
M2_REPO/org/jboss/jboss-aop-jdk50-client/4.0.5-GA/jboss-aop-jdk50-client-4.0.5-GA.jar


(I removed them from the /core/pom.xml so that I would not have to keep going back in and removing these...)

Note, right now I am just trying to get the JBoss Microcontainer alpha 9 version to run... later I am going to attemp to get the latest version going...

Note:  One other things... make sure you add /core/src/test/resources as a Source folder under Java Build Path -- Source Tab for your project.  Otherwise you will get the runtime exception: Cannot find embedded-jboss-beans.xml

Note 2:  OK... so the next problem I ran into was  the exception:
java.lang.NoClassDefFoundError: org/hibernate/annotations/common/reflection/ReflectionManager

I broke open the hibernate annotations .jar and noted that the above class is not in it... after a bit of searching on the Andromda forum, I found someone mention changing the main pom.xml hibernate sections as follows:



           
The change is to set both version to 3.2.0.ga versions... the versions in the one created for me were different and incompatible... you may be able to bring these up to the latest hibernate versions too... I have not tried that yet, but will be in the next couple of days.

run:
mvn install -Dmaven.test.skip
to bring down these new jars... note the -Dmaven.test.skip command which will tell it not to try to run the unit tests... without this, the build will fail ....following this run:
mvn eclipse:eclipse
Refresh your Eclipse environment...  (remember you will have to remove the .jars from the previous step again.  This step should be done first really, but I am just documenting the order I am running into these issues.)

One last step... I needed to modify the file core/src/test/resources/embedded-jboss-beans.xml to set the database username and password...

Find the section for the database you are using (mysql in this case)... add/or modify the username and/or password to match your local installation.