blob: d2c8ba3b0a6af6f2c842e719bf4e16a986605d78 [file] [log] [blame]
<!--
/***************************************************************************************************************************
* 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.
***************************************************************************************************************************/
-->
POJO Builders
<p>
Juneau parsers can use builders to instantiate POJOs.
This is useful in cases where you want to create beans with read-only properties.
Note that while it's possible to do this using the {@link oaj.annotation.Beanc @Beanc}
annotation, using builders can often be cleaner.
</p>
<p>
A typical builder usage is shown below:
</p>
<p class='bpcode w800'>
MyBean b = MyBean.<jsm>create</jsm>().foo(<js>"foo"</js>).bar(123).build();
</p>
<p>
The code for such a builder is shown below:
</p>
<p class='bpcode w800'>
<jk>public class</jk> MyBean {
<jc>// Read-only properties.</jc>
<jk>public final</jk> String <jf>foo</jf>;
<jk>public final int</jk> <jf>bar</jf>;
<jc>// Private constructor.</jc>
<jk>private</jk> MyBean(MyBeanBuilder b) {
<jk>this</jk>.<jf>foo</jf> = b.foo;
<jk>this</jk>.<jf>bar</jf> = b.bar;
}
<jc>// Static method that creates a builder.</jc>
<jk>public static</jk> MyBeanBuilder <jsm>create</jsm>() {
<jk>return new</jk> MyBeanBuilder();
}
<jc>// Builder class.</jc>
<jk>public static class</jk> MyBeanBuilder {
<jk>private</jk> String <jf>foo</jf>;
<jk>private int</jk> <jf>bar</jf>;
<jc>// Method that creates the bean.</jc>
<jk>public</jk> MyBean build() {
<jk>return new</jk> MyBean(<jk>this</jk>);
}
<jc>// Bean property setters.</jc>
<ja>@Beanp</ja>
<jk>public</jk> MyBeanBuilder foo(String foo) {
<jk>this</jk>.<jf>foo</jf> = foo;
<jk>return this</jk>;
}
<ja>@Beanp</ja>
<jk>public</jk> MyBeanBuilder bar(<jk>int</jk> bar) {
<jk>this</jk>.<jf>bar</jf> = bar;
<jk>return this</jk>;
}
}
}
</p>
<p>
The POJO class can be any type including beans.
Builders MUST be beans with one or more writable properties.
The bean properties themselves do not need to be readable (i.e. getters are optional).
</p>
<p>
Builders require two parts:
</p>
<ol>
<li>A way to detect and instantiate a builder using reflection.
<li>A way to instantiate a POJO from a builder.
</ol>
<p>
The first can be accomplished through any of the following:
</p>
<ul class='spaced-list'>
<li>A static <c>create()</c> method on the POJO class that returns a builder instance.
<p class='bcode w800'>
<jk>public static</jk> MyBuilder <jsm>create</jsm>() {...}
</p>
<li>A public constructor on the POJO class that takes in a single parameter that implements the {@link oaj.transform.Builder} interface.
<br>The builder class must have a public no-arg constructor.
<p class='bcode w800'>
<jk>public</jk> MyPojo(MyBuilder b) {...}
</p>
<li>A {@link oaj.annotation.Builder @Builder} annotation on the POJO class.
<br>The builder class must have a public no-arg constructor.
<p class='bcode w800'>
<ja>@Builder</ja>(MyBuilder.<jk>class</jk>)
<jk>public class</jk> MyPojo {...}
</p>
</ul>
<p>
The second can be accomplished through any of the following:
</p>
<ul class='spaced-list'>
<li>The existence of a <c>build()</c> method on the builder class.
<p class='bcode w800'>
<jk>public</jk> MyPojo build() {...}
</p>
<li>The existence of a public constructor on the POJO class that takes in the builder instance.
<p class='bcode w800'>
<jk>public</jk> MyPojo(MyBuilder b) {...}
</p>
</ul>
<ul class='seealso'>
<li class='ja'>{@link oaj.annotation.Builder}
<li class='jic'>{@link oaj.transform.Builder}
</ul>