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