| <?xml version="1.0" encoding="UTF-8"?> |
| <!-- |
| Licensed to the Apache Software Foundation (ASF) under one or more |
| contributor license agreements. See the NOTICE file distributed with |
| this work for additional information regarding copyright ownership. |
| The ASF licenses this file to You under the Apache License, Version 2.0 |
| (the "License"); you may not use this file except in compliance with |
| the License. You may obtain a copy of the License at |
| |
| http://www.apache.org/licenses/LICENSE-2.0 |
| |
| Unless required by applicable law or agreed to in writing, software |
| distributed under the License is distributed on an "AS IS" BASIS, |
| WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| See the License for the specific language governing permissions and |
| limitations under the License. |
| --> |
| <document xmlns="http://maven.apache.org/XDOC/2.0" |
| xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" |
| xsi:schemaLocation="http://maven.apache.org/XDOC/2.0 http://maven.apache.org/xsd/xdoc-2.0.xsd"> |
| <properties> |
| <title>Apache Commons Digester | Guide | Constructor rule</title> |
| <author email="dev@commons.apache.org">Commons Documentation Team</author> |
| </properties> |
| <body> |
| <section name="Constructor based rule"> |
| <p>One of the missing features of the old Digester releases is that the |
| <a href="../apidocs/org/apache/commons/digester3/ObjectCreateRule.html">ObjectCreateRule</a> works just with |
| the default empty constructor.</p> |
| <p>One limit that cannot be exceeded is the fact that constructor arguments cannot be extracted from inner |
| XML elements; that's because the <code>ObjectCreateRule</code> creates the object when the related XML |
| element <code>begins</code>, otherwise properties could not be set when parsing nested elements.</p> |
| <p>That is no longer true :) Constructor arguments can be extracted from <i>attributes</i> and |
| <i>nested elements</i> of the matching XML element for whom the <code>ObjectCreateRule</code> is triggered.</p> |
| <p><b>NOTE</b> this feature is available since release 3.2.</p> |
| |
| <subsection name="Using plain old Digester APIs"> |
| <p><code>ObjectCreateRule</code> has new APIs to configure the constructor arguments types; given for example |
| the XML snippet below:</p> |
| <source><root> |
| <bean super="true"> |
| <rate>9.99<rate/> |
| </bean> |
| </root></source> |
| <p>That has to be mapped to the bean:</p> |
| <source>class MyBean |
| { |
| |
| public MyBean( Double rate, Boolean super ) |
| { |
| ... |
| } |
| |
| }</source> |
| <p>Then the <code>Digester</code> instance can be configured as below:</p> |
| <source>ObjectCreateRule createRule = new ObjectCreateRule( MyBean.class ); |
| createRule.setConstructorArgumentTypes( boolean.class, double.class ); |
| |
| Digester digester = new Digester(); |
| digester.addRule( "root/bean", createRule ); |
| digester.addCallParam( "root/bean", 1, "super" ); |
| digester.addCallParam( "root/bean/rate", 0 );</source> |
| </subsection> |
| |
| <subsection name="Using the RulesBinder APIs"> |
| <p>The Binder APIs just allow expressing the same rule in a fluent way:</p> |
| <source>DigesterLoader loader = ( new AbstractRulesModule() |
| { |
| |
| @Override |
| protected void configure() |
| { |
| forPattern( "root/bean" ) |
| .createObject().ofType( MyBean.class ).usingConstructor( boolean.class, double.class ) |
| .then() |
| .callParam().fromAttribute( "super" ).ofIndex( 1 ); |
| forPattern( "root/bean/rate" ).callParam().ofIndex( 0 ); |
| } |
| |
| } );</source> |
| </subsection> |
| |
| <subsection name="Using the annotations"> |
| <p>Since 3.2, <a href="../apidocs/org/apache/commons/digester3/annotations/rules/ObjectCreate.html">ObjectCreate</a> |
| can be used to annotate constructors as well; with the introduction of |
| <a href="../apidocs/org/apache/commons/digester3/annotations/rules/Attribute.html">Attribute</a> annotation, |
| constructor based rules can be expressed like:</p> |
| <source>class MyBean |
| { |
| |
| @ObjectCreate( pattern = "root/bean" ) |
| public MyBean( @CallParam( pattern = "root/bean/rate" ) Double rate, |
| @CallParam( pattern = "root/bean", attributeName = "super" ) Boolean super ) |
| { |
| ... |
| } |
| |
| }</source> |
| </subsection> |
| |
| <subsection name="Using the XML meta-descriptor"> |
| <p>The XML ruleset supports as well the new constructor rule, <code><object-create-rule></code> supports |
| a new inner element <code><constructor-argument></code>:</p> |
| <source><digester-rules> |
| <pattern value="root/bean"> |
| <object-create-rule classname="MyBean |
| paramtypes="java.lang.Double,java.lang.Boolean"> |
| <constructor-argument attrname="rate" type="java.lang.Double" /> |
| <call-param-rule paramnumber="0" pattern="rate" /> |
| <call-param-rule paramnumber="1" attrname="super" /> |
| </object-create-rule> |
| </pattern> |
| </digester-rules></source> |
| </subsection> |
| </section> |
| |
| <section name="Default constructor arguments"> |
| <p>In order to provide that feature, Digester relies on <code>CGLIB</code> that needs to proxy the class of the |
| target object, to avoid constructors issues users can use the |
| <code>ObjectCreateRule#setDefaultConstructorArguments(Object...)</code> method to give safe construction |
| params to the constructor when creating the proxy; that method could be useful also when one parameter needs to |
| take a static value while the other is handled with a <code>CallParam</code> rule. If these are not specified, |
| the super constructor is called with nulls for Objects and default values for primitives.</p> |
| </section> |
| </body> |
| </document> |