You are viewing a plain text version of this content. The canonical link for it is here.
Posted to ojb-user@db.apache.org by De...@richer.ca on 2004/11/03 19:04:19 UTC

OJB XDoclet Module doesn't support multiple projects

Hi,

I have been using OJB since January and I use the XDoclet module to build 
the repository_user.xml file.  Everything has been going well, but 
recently I have been splitting our code base up into several subprojects 
and that has proven to be a much more difficult task than I originally 
anticipated.  For simplicity, lets assume I am splitting into only 2 
projects ... one called "Common" and another called "My Project".

Consider the following example ... one class in the My Project project 
(Foo) is referencing a class in the Common project (Bar):
/**
 * @ojb.class table="Foo"
 *
 * @ojb.field 
 *      name="barKey"
 *      column="BAR_KEY"
 *      jdbc-type="CHAR"
 *      length="8"
 */
public class Foo {
        /**
         * @ojb.reference foreignkey="barKey"
         */
        private Bar bar;
}

According to the documentation for the ojbdoclet task:

checks : none | basic | strict (default) 
The amount of the checks performed. Per default, strict checks are 
performed which means that for instance classes specified in an attribute 
(e.g. collection-class, row-reader etc.) are loaded from the classpath and 
checked. So in this mode it is necessary to have OJB as well as the 
processed classes on the classpath (using the classpathref attribute of 
the taskdef ant task above). If this is for some reason not possible, then 
use basic which performs most of the checks but does not load classes from 
the classpath. none does not perform any checks so use it with care and 
only if really necessary (in this case it would be helpful if you would 
post the problem to the ojb-user mailing list).

I have the following in my ant build file:

        <path id="classpath">
                <fileset dir="${common.build.dir}" />
        </path>

        <target 
                name="repository-files" 
                depends="compile" 
                description="Update the repository mapping files for 
ObJect-relational Bridge">

                <taskdef 
                        name="ojbdoclet" 
                        classname="xdoclet.modules.ojb.OjbDocletTask" 
                        classpathref="classpath"/>

                <ojbdoclet destdir="${src.java.dir}">
                        <fileset dir="${src.java.dir}" />
                        <ojbrepository destinationFile=
"repository_user.xml"/>
                </ojbdoclet>
        </target>

The XDoclet module *does* load classes from the classpath identified by 
the "classpathref" attribute of the taskdef, but the xdoclet module is not 
looking for the class itself but the *class descriptor* for Bar (which is 
sitting in Common's repository_user.xml file).  Because it can't find the 
class descriptor I get the following error message:
<<The class Bar referenced by bar in class Foo is unknown or not 
persistent>>

So, as a workaround I changed the mapping for Foo to this:
public class Foo {
        /**
         * @ojb.reference 
         *      foreignkey="barKey"
         *      class-ref="Bar"
         */
        private Bar bar;
}

and disabled checks by setting checks="none" on the ojbdoclet call in my 
ant build script.  This seems to fix the problem (i.e. it no longer tries 
to load Bar, but it does use the explicit class-ref provided).  However, 
by setting checks to "none", none of the class references to other classes 
that are in "My Project" resolve properly ... I get a repository_user.xml 
file with classref="".  I've decompiled and read through some of the 
xdoclet module's source code and it seems that the method "ensureClassRef" 
of ReferenceDescriptorConstraints has a side-effect of setting the class 
name of the classref, but this never occurs if checks is set to none.

If anyone else has experience splitting an OJB project across multiple 
subprojects, please let me know how you solved this problem.  Currently, I 
am using a hacked version of the OJB XDoclet module with a modified 
"ensureClassRef" method that *always* sets the classref regardless of the 
check level.  But really, there should be a way to load reference 
descriptors from another descriptor repository as part of the ojbdoclet 
task.  Maybe something like this:
                <ojbdoclet destdir="${src.java.dir}">
                        <externalDescriptorRepository>
                                <fileset dir="${common.dir}">
                                        <include 
name="repository_user.xml" />
                                </fileset>
                        </externalDescriptorRepository>

                        <fileset dir="${src.java.dir}" />
                        <ojbrepository destinationFile=
"repository_user.xml"/>
                </ojbdoclet>

The descriptor repositories identified by the nested fileset element would 
have to be merged into the global repository before checking the 
constraints of the java files found in the ${src.java.dir} ...

Thanks,
Phil Denis

Re: OJB XDoclet Module doesn't support multiple projects

Posted by Thomas Dudziak <to...@first.fhg.de>.
DenisP@richer.ca wrote:

>Hi,
>
>I have been using OJB since January and I use the XDoclet module to build 
>the repository_user.xml file.  Everything has been going well, but 
>recently I have been splitting our code base up into several subprojects 
>and that has proven to be a much more difficult task than I originally 
>anticipated.  For simplicity, lets assume I am splitting into only 2 
>projects ... one called "Common" and another called "My Project".
>
>Consider the following example ... one class in the My Project project 
>(Foo) is referencing a class in the Common project (Bar):
>  
>
<snip/>

>The XDoclet module *does* load classes from the classpath identified by 
>the "classpathref" attribute of the taskdef, but the xdoclet module is not 
>looking for the class itself but the *class descriptor* for Bar (which is 
>sitting in Common's repository_user.xml file).  Because it can't find the 
>class descriptor I get the following error message:
><<The class Bar referenced by bar in class Foo is unknown or not 
>persistent>>
>
>So, as a workaround I changed the mapping for Foo to this:
>public class Foo {
>        /**
>         * @ojb.reference 
>         *      foreignkey="barKey"
>         *      class-ref="Bar"
>         */
>        private Bar bar;
>}
>
>and disabled checks by setting checks="none" on the ojbdoclet call in my 
>ant build script.  This seems to fix the problem (i.e. it no longer tries 
>to load Bar, but it does use the explicit class-ref provided).  However, 
>by setting checks to "none", none of the class references to other classes 
>that are in "My Project" resolve properly ... I get a repository_user.xml 
>file with classref="".  I've decompiled and read through some of the 
>xdoclet module's source code and it seems that the method "ensureClassRef" 
>of ReferenceDescriptorConstraints has a side-effect of setting the class 
>name of the classref, but this never occurs if checks is set to none.
>
>If anyone else has experience splitting an OJB project across multiple 
>subprojects, please let me know how you solved this problem.  Currently, I 
>am using a hacked version of the OJB XDoclet module with a modified 
>"ensureClassRef" method that *always* sets the classref regardless of the 
>check level.  But really, there should be a way to load reference 
>descriptors from another descriptor repository as part of the ojbdoclet 
>task.  Maybe something like this:
>                <ojbdoclet destdir="${src.java.dir}">
>                        <externalDescriptorRepository>
>                                <fileset dir="${common.dir}">
>                                        <include 
>name="repository_user.xml" />
>                                </fileset>
>                        </externalDescriptorRepository>
>
>                        <fileset dir="${src.java.dir}" />
>                        <ojbrepository destinationFile=
>"repository_user.xml"/>
>                </ojbdoclet>
>
>The descriptor repositories identified by the nested fileset element would 
>have to be merged into the global repository before checking the 
>constraints of the java files found in the ${src.java.dir} ...
>  
>

Mhmm, reparsing existing repository-files is much more difficult than it 
sounds, basically because the module has no control about the parsing 
that XDoclet performs, and reparsing would mean generating XJavadoc 
nodes for at least some of the nodes, to satisfy XDoclet (the core, not 
the module) in some places.
One of the ideas for 1.1 btw. was to unify the models of OJB 
(ClassDescriptor etc.) and of the XDoclet module which might make this 
easier.
Another problem is that parts of XDoclet (the core, not the module) are 
static, e.g. holding the parsed source code entities, which often 
prohibits using an XDoclet module twice in the same Ant build script 
(more precisely, with the same Ant classloader).

I could however see whether an option could be added that controls which 
classes are written to the generated repository file. With this you 
would still have to provide the source for Bar to the second task 
invocation, but it would not write a class descriptor to the repository 
file.

Tom


---------------------------------------------------------------------
To unsubscribe, e-mail: ojb-user-unsubscribe@db.apache.org
For additional commands, e-mail: ojb-user-help@db.apache.org