How to do OpenJPA enhancement with Ant + IntelliJ IDEA - intellij-idea

This is driving me crazy and I'm shocked that official documentation is absolutely useles.
Here is what I have:
IntelliJ IDEA 11
OpenJPA 2.1.1
Since openjpa is added into list of used libraries I already had classpath to OpenJPA which looks like this
<path id="library.openjpa.classpath">
<fileset dir="${basedir}/lib/openjpa">
<patternset refid="library.patterns"/>
</fileset>
</path>
According to official documentation I added following target
<target name="enhance">
<copy includeemptydirs="false" todir="${basedir}/lib/openjpa">
<fileset dir="src" excludes="**/*.launch, **/*.java"/>
</copy>
<taskdef name="openjpac" classname="org.apache.openjpa.ant.PCEnhancerTask">
<classpath refid="library.openjpa.classpath"/>
</taskdef>
<openjpac>
<classpath refid="library.openjpa.classpath"/>
</openjpac>
</target>
It gives me exception
C:\work\prj\build.xml:283: org.apache.openjpa.util.MetaDataException:
MetaDataFactory could not be configured
(conf.newMetaDataFactoryInstance() returned null). This might mean
that no configuration properties were found. Ensure that you have a
META-INF/persistence.xml file, that it is available in your classpath,
or that the properties file you are using for configuration is
available. If you are using Ant, please see the or
attributes of the task's nested element.
This can also occur if your OpenJPA distribution jars are corrupt, or
if your security policy is overly strict.
I tested with Process Monitor and can see that it opens and reads persistence.xml.
Some person filed bug having problems I have and the answer he got was that finding persistence.xml is not a source of problem.
Questions are:
What can I do to make it work ?
Can I make it work by skipping need for persistence.xml and just specifying pattern for .class files I want to be enhanced ?
It's more Ant question. How can I make OpenJPA enhancer to look for persistence.xml in directory other than where openjpa-2.1.1.jar resides ?

So I couldn't make it work without undocumented propertiesFile. Here is version that works for me. Also specifying persistence-unit via # makes it fail with NullReferenceException.
<target name="enhance">
<taskdef name="openjpac" classname="org.apache.openjpa.ant.PCEnhancerTask">
<classpath refid="library.openjpa.classpath"/>
</taskdef>
<openjpac>
<classpath refid="library.openjpa.classpath"/>
<classpath location="${reporting.output.dir}"/>
<config propertiesFile = "${basedir}/src/META-INF/persistence.xml"/>
</openjpac>
</target>

It appears that you might have missed an important part from the documentation. Your library.openjpa.classpath is missing a reference to your Entities, and the location of the persistence.xml file. Try adding that and see how it goes.
<path id="jpa.enhancement.classpath">
<pathelement location="bin"/> <!-- add something like this -->
<!-- lib contains all of the jars that came with the OpenJPA binary download -->
<fileset dir="lib">
<include name="**/*.jar"/>
</fileset>
</path>

Related

How to copy runtime libraries without the provided ones in IVY

I thought I wouldn't need to ask this but I am not having any progress.
The solution to this question:
How are maven scopes mapped to ivy configurations by ivy actually addresses question but in its theoretical part.
I have this configuration:
<conf name="compile" description="???" />
<conf name="runtime" description="???" extends="compile" />
<conf name="test" description="???" extends="runtime" />
<conf name="provided" description="???" />
Assume I have this dependency:
<dependency org="org.apache.tomcat" name="servlet-api" rev="6.0.16" transitive="false" />
What I want is: when I invoke the ivy:retrieve to copy the libraries to the .war lib directory before bundling it, I want only to copy all runtime (and compile implicitly) but no servlet-api.
so how to use ivy:retrieve then?
<ivy:retrieve conf="WHAT_TO_PUT_HERE" />
and how to configure the dependency:
<dependency conf="WHAT_IS_THE_CONF_MAPPING" org="org.apache.tomcat" name="servlet-api" rev="6.0.16" transitive="false" />
I'm plateauing here, so please any help would be appreciated.
Knowing that the ivy.xml for servlet-api defines the artifact with
conf="master"
So I think the question is how to 'really' map Provided scope of maven to the provided configuration of IVY.
This is how you map a dependency onto the local "provided" configuration:
<dependency org="org.apache.tomcat" name="servlet-api" rev="6.0.16" conf="provided->master"/>
The configuration mapping works as follows:
provided->master
^ ^
| |
Local Remote
config config
As explained in the answer the special "master" configuration contains only the artifact published by this module itself, with no transitive dependencies:
How are maven scopes mapped to ivy configurations by ivy
This means the "transitive=false" attribute is not required.
Update
How you use the configuration is up to you. The first option is simpler, but I prefer the second approach because my configuration reports match my classpath contents
Option 1
You can create a single classpath as follows:
<ivy:cachepath pathid="compile.path" conf="compile,provided"/>
This can then be used in the javac task as follows:
<javac ... classpathref="compile.path">
..
Option 2
Or I prefer to have a one-2-one mapping between configurations and classpaths:
<ivy:cachepath pathid="compile.path" conf="compile"/>
<ivy:cachepath pathid="provide.path" conf="provided"/>
The problem with the latter approach is that the javac task need to have the classpath usage explicitly stated as follows:
<javac ...
<classpath>
<path refid="compile.path"/>
<path refid="provided.path"/>
</classpath>
I think this explicitly explains how you use this special provided scope, but it's really up to you.

ivysettings.xml: Can I "modify" the default settings without modifying the jar or completely replacing them?

I've been going through the Ivy documentation and I have a question about the default ivysettings.xml found inside the ivy.jar.
All I want to do is change the public repository to a local Maven repository we have. That's it. I could copy all of the ivysettings*.xml files into my project, and use <ivy:settings> to point to it, but that duplicates a lot of stuff. I could also modify the ivy.jar, but that adds maintenance headaches. Developers have to use my ivy.jar, and if we go to a new version, I'd have to modify it again.
So, how do I keep all of the standard Ivy settings and simply switch the repository to use? I simply want to overlay my changes onto what Ivy already has.
And two more questions:
What's the difference between the ivyconf*.xml files and the ivysettings*.xml files? Why are there duplicate configurations in Ivy?
What's a good book on Ivy? I'm right now using Manning's Ant in Action which covers Ivy in a somewhat summary way and is a bit dated. The resources on the Ivy website itself are awful.
That's my ivysettings.xml file
<ivysettings>
<include url="${ivy.default.settings.dir}/ivysettings.xml"/>
<resolvers>
<chain name="download-chain" changingPattern=".*" checkmodified="true" >
<ibiblio name="maven" m2compatible="true" />
</chain>
</resolvers>
</ivysettings>
Notice that I write my extra resolvers here, but use everything else from the standard one, which is indicated in the url. This will loads the settings from the ivysettings.xml in the ivy.jar file.
As to the ivyconf*.xml. I think it is deprecated now. Ivysettings is the new way of doing this.
The resources are pretty awful. I totally concur to that. However, lots of answers in the stackoverflow.com were verbose enough and actually try to anticipate problems
Mark O'Connor's answers are particularly verbose and straight to the point. You have to embrace the fact that you are learning something new, just give it time.
Finally figured it out.
I copied the ivysettings.xml file from the jar and made a slight modification. Note that the first include points to an XML file in ivy ${ivy.lib.dir} and not to ${ivy.default.settings.dir}:
<ivysettings>
<settings defaultResolver="default"/>
<include file="${ivy.lib.dir}/ivysettings-public.xml"/>
<include url="${ivy.default.settings.dir}/ivysettings-shared.xml"/>
<include url="${ivy.default.settings.dir}/ivysettings-local.xml"/>
<include url="${ivy.default.settings.dir}/ivysettings-main-chain.xml"/>
<include url="${ivy.default.settings.dir}/ivysettings-default-chain.xml"/>
</ivysettings>
I have my own ivysettings-public.xml which is the same as the default, but now defines a root to my repository. (Yes, it's localhost for now, but I'll set it to an actual server once I get everything resolved):
<ivysettings>
<resolvers>
<ibiblio name="public" m2compatible="true"
root="http://localhost:8081/artifactory/repo" />
</resolvers>
</ivysettings>
Now, in my build.xml, I have the following:
<property name="ivy.lib.dir" value="${basedir}/ivy.lib"/>
<taskdef uri="ivylib:org.apache.ivy.ant"
resource="org/apache/ivy/ant/antlib.xml">
<classpath>
<fileset dir="${ivy.lib.dir}">
<include name="ivy.jar"/>
<include name="ivy-*.jar"/>
</fileset>
</classpath>
</taskdef>
<ivy:configure file="${ivy.lib.dir}/ivysettings.xml" override="true"/>
That seems to do the trick.
In your build.xml include following:
<property name="ivy.settings.dir" value="PATH OF SETTINGS" />
<property file="${ivy.settings.dir}/ivysettings.properties" />
<ivy:settings file="${ivy.settings.dir}/ivysettings.xml" />

Creating DDL scripts from JPA/Hibernate Annotation Classes Using ANT

I would like to generate SQL DDL scripts from Hibernate/JPA Annotation Classes using ANT.
Below is the ANT script that I wrote based on Hibernate Dev Docs URL: http://docs.jboss.org/hibernate/orm/4.1/devguide/en-US/html_single/
<project name="yourmarketnet" default="all" basedir=".">
<target name="ddl_generation">
<!-- paths to required jars -->
<path location="web/WEB-INF/lib/hibernate-annotations.jar" />
<path location="web/WEB-INF/lib/ejb3-persistence.jar" />
<path location="web/WEB-INF/lib/hibernate-entitymanager.jar" />
<path location="web/WEB-INF/lib/javaassist.jar" />
<path location="web/WEB-INF/lib/hibernate-tools.jar"/>
<taskdef name="hibernatetool" classname="org.hibernate.tool.ant.HibernateToolTask.jar">
<classpath path="${build.dir}/web/WEB-INF/lib/hibernate-tools.jar"/>
</taskdef>
<!-- output destination -->
<hibernatetool destdir="${build.dir}">
<!-- were the annotation beans files are located-->
<classpath>
<path location="${build.dir}/web/WEB-INF/classes/com/yourmarketnet/beans" />
</classpath>
<!-- list exporters here -->
<hbm2ddl
export="false"
update="false"
drop="true"
create="true"
outputfilename="myApps.ddl"
delimiter=";"
format="false"
haltonerror="true"/>
</hibernatetool>
</target>
</project>
Im getting ERROR taskdef class org.hibernate.tool.ant.HibernateToolTask cannot be found
using the classloader AntClassLoader[]
I also checked to see if hibernate-tools.jar was actually in the path and it was (C:\Users\naim\Documents\NetBeansProjects\yourmarketnet\build\web\WEB-INF\lib\hibernate-tools.jar)
Can someone please tell me step by step how to fix/debug this issue , thanks.
Error message clearly tells you that ant can't find your tools. When you declare
<taskdef name="hibernatetool" classname="org.hibernate.tool.ant.HibernateToolTask" >
<classpath path="${build.dir}/web/WEB-INF/lib"/>
</taskdef>
it's already wrong because tool classes are not in directory but in jar. Secondly, your intent seems to be to use ${build.dir} as output location, so why would it contain tool classes? Anyway, you didn't even define this directory.
So if you really have your hibernate-tools.jar in web/WEB-INF/lib, you probably want something like
<taskdef name="hibernatetool" classname="org.hibernate.tool.ant.HibernateToolTask" >
<classpath path="web/WEB-INF/lib/hibernate-tools.jar"/>
</taskdef>
Note that it's relative to your project directory.

How to run liquibase on linux system

I am working with Liquibase on Linux, does anyone know how to run the datbasechangelog.xml file from the Linux prompt step by step? And what's the idea behind databasechangelog and how it works?
For our projects, we have set up ant tasks to do this. So, for example, if you want to run the migrations, the ant file may look like the following:
ant-migrations.xml
<project name="Migrations" basedir="." default="update-database">
<property file="./liquibasetasks.properties" />
<path id="master-classpath" description="Master classpath">
<fileset dir="..\lib">
<include name="*.jar" />
</fileset>
</path>
<target name="update-database">
<fail unless="db.changelog.file">db.changelog.file not set</fail>
<fail unless="database.url">database.url not set</fail>
<fail unless="database.username">database.username not set</fail>
<fail unless="database.password">database.password not set</fail>
<taskdef resource="liquibasetasks.properties">
<classpath refid="master-classpath"/>
</taskdef>
<updateDatabase
changeLogFile="${db.changelog.file}"
driver="${database.driver}"
url="${database.url}"
username="${database.username}"
password="${database.password}"
promptOnNonLocalDatabase="${prompt.user.if.not.local.database}"
dropFirst="false"
classpathref="master-classpath"
/>
</target></project>
Make sure your liquibase jar file(s) are referenced in the classpath element.
The properties file contains the references that are particular to your environment:
liquibasetasks.properties
db.changelog.file=YOUR_MIGRATION_FILE.xml
#################################
## DB Settings
#################################
database.driver=
database.username=
database.password=
database.url=
Ok, so now we have the ant task set up and configured.. with all of that saved, you should be able to run the migration by typing the following at the command prompt:
linux>ant -f ant-migrations.xml update-database
Hope that helps!

ANT How to use the lexically scoped properties in Ant 1.8?

I have script that dosn't work becouse property once set became unwritable
<target name="test" >
<fileset id="dir1" dir="./dir1"/>
<fileset id="dir2" dir="./dir2"/>
<pathconvert property="path.converted" refid="dir1"/>
<echo message="${path.converted}"/>
<property name="path.converted" value="set this property manually"/>
<echo>${path.converted}</echo>
<pathconvert property="path.converted" refid="dir2"/>
<echo message="${path.converted}"/>
</target>
always echoed the same result, but I want that echoes was different
I read in Apache Ant 1.8.0 release, that
Lexically scoped local properties,
i.e. properties that are only defined
inside a target, sequential block or
similar environment. This is very
useful inside of s where a
macro can now define a temporary
property that will disappear once the
task has finished.
How to use them?
I found solution. Use local task
<target name="direct" depends="">
<fileset id="dir1" dir="./dir1"/>
<fileset id="dir2" dir="./dir2"/>
<!--<property name="path.converted" value="0"/>-->
<local name="path.converted"/>
<pathconvert property="path.converted" refid="dir1"/>
<echo message="${path.converted}"/>
<local name="path.converted"/>
<property name="path.converted" value="0"/>
<echo>${path.converted}</echo>
<local name="path.converted"/>
<pathconvert property="path.converted" refid="dir2"/>
<echo message="${path.converted}"/>
</target>
I would simply use different names for path.converted for the example above.
path.converted.1, path.converted.2 etc.
If you would have created a macrodef you should definitely use the local task to make the property local.