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