Hi Chris,

I checked in a small work-around in the CVS.

To disable the check for no-argument constructor just do the following:

    <class name="Pet" verify-constructable="false">
 
      <field name="name" type="java.lang.String">
        <bind-xml name="name" node="attribute" />
      </field>
 
      <field name="age" type="java.lang.Integer">
        <bind-xml name="age" node="attribute" />
      </field>
    </class>

Make sure you use the DTD from the CVS and not the one from the website
or you might get validation errors when loading the mapping file.

Anyway I am not sure I will keep that fix in the long run, but it will
be available until another solution presents itself. 

--Keith

Keith Visco wrote:
> 
> Hi Chris
> 
> One workaround to the issue of not-constructable is to use an interface
> or abstract class as such:
> 
> public interface IPet {
> 
>    public int getAge();
>    public String getName();
> 
>    public void setAge(int age);
>    public void setName(String name);
> }
> 
> And then have your Pet class implement the interface (or extend the
> abstract class):
> 
> public class Pet implements IPet {
> 
> }
> 
> And then use IPet in the mapping file instead of Pet as such:
> 
>    <class name="IPet">
> 
>      <field name="name" type="java.lang.String">
>        <bind-xml name="name" node="attribute" />
>      </field>
> 
>      <field name="age" type="java.lang.Integer">
>        <bind-xml name="age" node="attribute" />
>      </field>
>    </class>
> 
> I know it's a pain to have to do that...but it's only a work-around to
> allow the specification of your Pet class without having to rely on
> default introspection.
> 
> I'll try to look at the default constructor and see if I can write a
> by-pass for that. In most cases we want to throw the exception because
> people expect Castor to create the instance of the class, but in your
> case Castor won't be creating the instance so it makes sense not to
> throw the exception. There are a couple quick solutions I can think of:
> 
> 1. Remove the mapping restriction and let it be a runtime unmarshalling
> error.
> 
> 2. Provide a way in the mapping file to specify that the class won't
> need to be created by
>    Castor and therefore it doesn't matter if it's not constructable with
> zero args.
> 
> Also we could possibly check that all occurances of fields that use the
> "Pet" class provide their own handler or create Method and if so throw
> no exception. This would take a bit longer to implement but might be the
> better solution.
> 
> --Keith
> 
> Keith Visco wrote:
> >
> > Hi Chris,
> >
> > I got it to work by simply commenting out the class mapping for Pet as
> > such:
> >
> >   <!--
> >   <class name="Pet">
> >     <map-to xml="pet" />
> >
> >     <field name="name" type="java.lang.String">
> >       <bind-xml name="name" node="attribute" />
> >     </field>
> >
> >     <field name="age" type="java.lang.Integer">
> >       <bind-xml name="age" node="attribute" />
> >     </field>
> >   </class>
> >   -->
> >
> > and letting Castor introspect the class.
> >
> > The MappingLoader doesn't like the fact the the Pet class doesn't have a
> > default (no arg) constructor.
> >
> > I'll have to look into removing that limitation from the MappingLoader.
> >
> > --Keith
> >
> > Chris Bedford wrote:
> > >
> > > Keith:
> > >
> > > I apologize for being thick, but I'm still lost on this one...
> > >
> > > I have created a real simple example that tries to follow your advice to
> > > Matthias of setting the type of the object that the
> > > handler is expecting to receive.....  in my case I assume its not a string
> > > (but I'm not 100% sure)...
> > >
> > > I'd be much obliged if you could you clue me in on what I'm messing up in
> > > the code below ->
> > > (the listing is a bit long, but its a simple unmarshal/marshal of  this
> > > xml ->
> > >
> > > <person name="Bob" age="44">
> > >   <pet name="spot" age="2"/>
> > > </person>
> > >
> > > ////////////////// mapping.xml
> > >
> > > <!DOCTYPE mapping PUBLIC "-//EXOLAB/Castor Object Mapping DTD
> > > Version 1.0//EN"
> > > "http://castor.exolab.org/mapping.dtd";>
> > > <mapping>
> > >   <class name="Person">
> > >     <map-to xml="person" />
> > >
> > >     <field name="name" type="java.lang.String">
> > >       <bind-xml name="name" node="attribute" />
> > >     </field>
> > >
> > >     <field name="age" type="java.lang.Integer">
> > >       <bind-xml name="age" node="attribute" />
> > >     </field>
> > >
> > >     <field name="pet" type="Pet"  handler="Handler">
> > >       <bind-xml name="pet" node="element"/>
> > >     </field>
> > >   </class>
> > >
> > >   <class name="Pet">
> > >     <map-to xml="pet" />
> > >
> > >     <field name="name" type="java.lang.String">
> > >       <bind-xml name="name" node="attribute" />
> > >     </field>
> > >
> > >     <field name="age" type="java.lang.Integer">
> > >       <bind-xml name="age" node="attribute" />
> > >     </field>
> > >   </class>
> > > </mapping>
> > >
> > > ///////////////   FieldHandlerDemo.java
> > > import org.exolab.castor.mapping.Mapping;
> > > import org.exolab.castor.mapping.MappingException;
> > >
> > > import org.exolab.castor.xml.Unmarshaller;
> > > import org.exolab.castor.xml.Marshaller;
> > >
> > > import java.io.IOException;
> > > import java.io.FileReader;
> > > import java.io.OutputStreamWriter;
> > >
> > > import org.xml.sax.InputSource;
> > >
> > > public class FieldHandlerDemo {
> > >
> > >     public static void main(String args[]) {
> > >
> > >         Mapping      mapping = new Mapping();
> > >
> > >         try {
> > >             // 1. Load the mapping information from the file
> > >             mapping.loadMapping( "mapping.xml" );
> > >
> > >             // 2. Unmarshal the data
> > >             Unmarshaller unmar = new Unmarshaller(mapping);
> > >             Person person = (Person)unmar.unmarshal(new InputSource(new
> > > FileReader("person.xml")));
> > >
> > >             // 3. Do some processing on the data
> > >             person.setName("Frank");
> > >
> > >             // 4. marshal the data with the total price back and print the
> > > XML in the console
> > >             Marshaller marshaller = new Marshaller(new
> > > OutputStreamWriter(System.out));
> > >             marshaller.setMapping(mapping);
> > >             marshaller.marshal(person);
> > >             System.out.println("");
> > >
> > >         } catch (Exception e) {
> > >             System.out.println(e);
> > >             return;
> > >         }
> > >     }
> > > }
> > >
> > > public class Pet {
> > >     private int         age;
> > >     private String      name;
> > >
> > >     //////////////////////////////////////////////////////////////////////
> > >     //   Getters
> > >
> > >     public int getAge()
> > >     {
> > >             return age;
> > >     }
> > >
> > >     public String getName()
> > >     {
> > >             return name;
> > >     }
> > >
> > >     //////////////////////////////////////////////////////////////////////
> > >     //   Setters
> > >
> > >     public void setAge(int  age)
> > >     {
> > >             this.age = age;
> > >     }
> > >
> > >     public void setName(String  name)
> > >     {
> > >             this.name = name;
> > >     }
> > >
> > >     //////////////////////////////////////////////////////////////////////
> > >     //   Constructors
> > >
> > >     Pet(int age, String name) {
> > >         this.age = age;
> > >         this.name = name;
> > >     }
> > >
> > > }
> > >
> > > public class Person {
> > >
> > >     private Pet     pet;
> > >     private String  name;
> > >     private int     age;
> > >
> > >     //////////////////////////////////////////////////////////////////////
> > >     //   Getters
> > >
> > >     public Pet getPet()
> > >     {
> > >         return pet;
> > >     }
> > >
> > >     public int getAge()
> > >     {
> > >             return age;
> > >     }
> > >
> > >     public String getName()
> > >     {
> > >             return name;
> > >     }
> > >
> > >     //////////////////////////////////////////////////////////////////////
> > >     //   Setters
> > >
> > >     public void setPet(Pet  pet)
> > >     {
> > >         this.pet = pet;
> > >     }
> > >
> > >     public void setAge(int  age)
> > >     {
> > >             this.age = age;
> > >     }
> > >
> > >     public void setName(String  name)
> > >     {
> > >             this.name = name;
> > >     }
> > >
> > > }
> > >
> > > ///////// Handler.java
> > > import org.exolab.castor.mapping.*;
> > >
> > > public class Handler implements FieldHandler   {
> > >     public Object newInstance(Object parent) throws IllegalStateException {
> > >         System.out.println("newInstance called");
> > >         return new Pet(0, "dummy");
> > >     }
> > >
> > >     public Object getValue(Object object)   throws IllegalStateException {
> > >         return ((Person)object).getPet();
> > >     }
> > >
> > >     public void setValue(Object object, Object value)
> > >                                             throws IllegalStateException,
> > > IllegalArgumentException {
> > >         Person  person = (Person) object;
> > >         Pet     petVal = (Pet) value;
> > >         person.setPet(petVal);
> > >     }
> > >
> > >     public void resetValue(Object object)       throws
> > > IllegalStateException, IllegalArgumentException {
> > >     }
> > >
> > >     public void checkValidity(Object object)    throws ValidityException,
> > > IllegalStateException {
> > >     }
> > > }
> > >
> > > ----- Original Message -----
> > > From: "Keith Visco" <[EMAIL PROTECTED]>
> > > To: <[EMAIL PROTECTED]>
> > > Sent: Monday, December 16, 2002 1:10 PM
> > > Subject: Re: [castor-dev] NotConstructable Exception and FieldHandler
> > >
> > > >
> > > > Change you mapping to the following:
> > > >
> > > >      <class name="com.Coordinates" access="shared">
> > > >          <description>Default mapping for Coordinates</description>
> > > >          <map-to xml="Coordinates"/>
> > > >          <field name="format" type="string"
> > > > handler="com.CoordinateFormatEnumFieldHandler">
> > > >              <bind-xml name="Format" node="attribute"/>
> > > >          </field>
> > > >      </class>
> > > >
> > > > Note that I changed the "type" to "string" instead of
> > > > "com.CoordinateFormatEnum". When using a handler you need to specify the
> > > > type that the handler is expecting to recieve in a call to the setObject
> > > > and returns in a call to the getObject.
> > > >
> > > > --Keith
> > > >
> > > > > Matthias David wrote:
> > > > >
> > > > > Hi,
> > > > >
> > > > > I have written a FieldHandler for a class (CoordinateFormatEnum) that
> > > > > has no public constructor. When Unmarshalling I get the following
> > > > > exception:
> > > > >
> > > > > Nested error: org.exolab.castor.mapping.MappingException: The Java
> > > > > class CoordinateFormatEnum is not constructable -- it does not contain
> > > > > a default public constructor)
> > > > >
> > > > > The problem is that the class CoordinateFormatEnum is a tool-generated
> > > > > class, so I have no chance to make the constructor public. So How can
> > > > > this problem be solved? I thought that the Unmarshaller does not need
> > > > > to call the constructor of the class since the FieldHandler is
> > > > > responsible for that, e.g. using the method "newInstance".
> > > > >
> > > > > Here's the handler's code:
> > > > >
> > > > > public class CoordinateFormatEnumFieldHandler implements FieldHandler
> > > > > {
> > > > >
> > > > >     public Object getValue(Object object)
> > > > >             throws IllegalStateException {
> > > > >         return ((Coordinates)object).getFormat().getValue();
> > > > >     }
> > > > >
> > > > >     public void setValue(Object object, Object value)
> > > > >             throws IllegalStateException, IllegalArgumentException {
> > > > >
> > > > >
> > > ((Coordinates)object).setFormat(CoordinateFormatEnum.fromString((String)valu
> > > e));
> > > > >
> > > > >     }
> > > > >
> > > > >     public void resetValue(Object object)
> > > > >             throws IllegalStateException, IllegalArgumentException {
> > > > >     }
> > > > >
> > > > >     public void checkValidity(Object object)
> > > > >             throws ValidityException, IllegalStateException {
> > > > >     }
> > > > >
> > > > >     public Object newInstance(Object parent)
> > > > >             throws IllegalStateException {
> > > > >         return CoordinateFormatEnum.Mercator;
> > > > >     }
> > > > > }
> > > > >
> > > > > And here's the mapping:
> > > > >
> > > > >     <class name="com.Coordinates" access="shared">
> > > > >         <description>Default mapping for Coordinates</description>
> > > > >         <map-to xml="Coordinates"/>
> > > > >         <field name="format" type="com.CoordinateFormatEnum"
> > > > > handler="com.CoordinateFormatEnumFieldHandler">
> > > > >             <bind-xml name="Format" node="attribute"/>
> > > > >         </field>
> > > > >     </class>
> > > > >
> > > > > Any clues for that?
> > > > >
> > > > > Thanks,
> > > > >  Matthias.
> > > >
> > > > -----------------------------------------------------------
> > > > If you wish to unsubscribe from this mailing, send mail to
> > > > [EMAIL PROTECTED] with a subject of:
> > > > unsubscribe castor-dev
> > > >
> > >
> > > -----------------------------------------------------------
> > > If you wish to unsubscribe from this mailing, send mail to
> > > [EMAIL PROTECTED] with a subject of:
> > >         unsubscribe castor-dev
> >
> > -----------------------------------------------------------
> > If you wish to unsubscribe from this mailing, send mail to
> > [EMAIL PROTECTED] with a subject of:
> >         unsubscribe castor-dev
> 
> -----------------------------------------------------------
> If you wish to unsubscribe from this mailing, send mail to
> [EMAIL PROTECTED] with a subject of:
>         unsubscribe castor-dev

----------------------------------------------------------- 
If you wish to unsubscribe from this mailing, send mail to
[EMAIL PROTECTED] with a subject of:
        unsubscribe castor-dev

Reply via email to