Let me introduce my code then I will ask a question.
This is just an example. I would like to learn something new if it is possbile.
BaseClass.java
public class BaseClass {
private String baseName;
BaseClass(String baseName){
this.baseName = baseName;
}
//getters and setters
}
MyClass.java
public class MyClass extends BaseClass {
private boolean isTest;
private String name;
MyClass(){
}
MyClass(String baseName){
super(baseName);
this.isTest = true;
}
//getters and setters
}
MyClassController.java
#Controller
public class MyClassController {
#GetMapping(value="/")
#ResponseBody
public String myClassController(#RequestBody MyClass myClass) {
return "index";
}
}
JSON request:
{
"name": "Name for BaseClass"
}
So, I send name e.g.: Name for BaseClass. I want to set this name for variable BaseName in BaseClass through constructor. #RequestBody needs no atribute constructor so I cannot use there this second constructor with arguments. I can handle this e.g. for using additional method:
Additional method in MyClass.java
public MyClass setValues(String baseName){
super(baseName);
this.isTest = true;
return this;
}
New MyController.java
#Controller
public class MyClassController {
#GetMapping(value="/")
#ResponseBody
public String myClassController(#RequestBody MyClass myClass) {
myClass.setValues(myClass.getName());
//more uses for myClass
return "index";
}
}
Is there any better way to do something like this in more "professional" way?
If you're married to the current inheritance structure, you can use HttpMessageConverter to customize the way Spring deserializes HTTP requests.
public class MyClassConverter extends AbstractHttpMessageConverter<MyClass> {
public MyClassConverter() {
super(new MediaType("text", "myClass"));
}
#Override
protected boolean supports(Class<?> clazz) {
return MyClass.class.isAssignableFrom(clazz);
}
#Override
protected MyClass readInternal(Class<? extends MyClass> clazz, HttpInputMessage inputMessage)
throws IOException, HttpMessageNotReadableException {
// Deserialize JSON request
MyClass inputObject = new MyClass(name);
return inputObject;
}
#Override
protected void writeInternal(MyClass myClass, HttpOutputMessage outputMessage) {
// Serialize MyClass object
}
}
Detailed example
Although it's not clear I'm assuming name and baseName are meant to be the same value. In that case it might make sense for BaseClass to be an abstract class or interface.
abstract class:
public class MyClass extends BaseClass {
private String name;
// constructors
#Override
String getName() {
return name;
}
// setters
}
public abstract class BaseClass {
abstract String getName();
}
interface:
public class MyClass implements DtoWithName {
private String name;
// constructors
#Override
String getName() {
return name;
}
// setters
}
public interface DtoWithName {
String getName();
}
Also, I can't tell much about your use-case from the given example, but you should read into Composition over inheritance to make sure you're going about it the right way. With DTOs in particular usually simple is best.
I have an abstract class that contains common methods:
public abstract class AbstractDAO<T> implements IFindTradeDAO {
#Autowired
private JdbcTemplate jdbcTemplate;
#Override
public List<Trade> findOne(final int eventId) {
return jdbcTemplate.query(getOneQuery(), new Object[]{eventId}, new RowMapper());
}
#Override
public List<Event> getAll() {
return jdbcTemplate.queryForList(getAllQuery(), Event.class);
}
protected abstract String getOneQuery();
protected abstract String getAllQuery();
}
The derived class which provides type specific queries:
#Repository
public class TypeA extends AbstractDAO implements IFindTradeDAO {
private static final String FIND = "sql/findA.sql";
private static final String GET = "sql/getA.sql";
#Override
protected String getOneQuery() {
return FIND;
}
#Override
protected String getAllQuery() {
return GET;
}
#Repository
public class TypeB extends AbstractDAO implements IFindTradeDAO {
private static final String FIND = "sql/findB.sql";
private static final String GET = "sql/getB.sql";
#Override
protected String getOneQuery() {
return FIND;
}
#Override
protected String getAllQuery() {
}
}
Given I have this class structure, I want to invoke the getAllQuery() for all the derived class sql e.g. for TypeA and TypeB on schedule using
org.springframework.scheduling.annotation.Scheduled;
#Component
public class GetAllEvents {
#Scheduled
public void processUnprocessedEvents() {
//invoke getAllQuery for all DAOS and combine results
}
}
I am not quite sure how I can derive a Component that will invoke all? Is there technique or example I can use to achieve this?
I'm not a Java programmer, but in .NET you'd need to put them all into some type of list or array, and call the function on each item.
So maybe create a method called Add(IFindTradeDAO dao) which adds each one to a list. And then call the method on each of those items.
public interface A extends C {
String getCh();
String getId();
String getReview();
}
public interface B extends C {
String getCh();
String getId();
String getReview();
}
#Data
#Builder
public class AImpl implements A{
private String ch;
private String id;
private String review;
}
#Data
#Builder
public class BImpl implements B{
private String ch;
private String id;
private String review;
}
so now to use the builders of these I do:
return AImpl.builder()
.ch("ch")
.id("id")
.review("somerview");
For B I do:
return BImpl.builder()
.ch("ch1")
.id("id1")
.review("some new review");
Is there a way where I can make this builder part into a function? I dont like the idea of repeating the same code again. Like where I can pass id channel and review in a function and I can the object?
Disclaimer: I have never really dealt with builders so there might be a really much better option :D
This approach writes builders for each interface individually.
This does require that the interfaces provide a setter method.
Using generics, the methods of the RootBuilder and BaseABuilder return an instance of the ImplABuilder so that the chain can continue properly.
This is a very simple implementation of the Thistype generic which in other languages exists by default. This implementation also relies on casting to the actual Thistype but if you set the generics properly, that shouldnt be an issue.
public class Test
{
public static void main(String[] args)
{
ImplA implA = ImplA
.builder()
.id("id")
.description("description")
.valueA("a")
.build();
}
}
public interface Root
{
String getId();
void setId(String id);
String getDescription();
void setDescription(String description);
}
public class RootBuilder<Thistype extends RootBuilder<Thistype, Instance>, Instance extends Root>
{
protected final Instance object;
RootBuilder(Instance object)
{
this.object = object;
}
public Thistype id(String value)
{
object.setId(value);
return (Thistype)this;
}
public Thistype description(String value)
{
object.setDescription(value);
return (Thistype)this;
}
public Instance build()
{
return object;
}
}
public interface BaseA extends Root
{
String getValueA();
void setValueA(String valueA);
}
public class BaseABuilder<Thistype extends BaseABuilder<Thistype, Instance>, Instance extends BaseA> extends RootBuilder<Thistype, Instance>
{
protected Instance object;
BaseABuilder(Instance object)
{
super(object);
}
public Thistype valueA(String value)
{
object.setValueA(value);
return (Thistype)this;
}
}
public interface BaseB extends Root
{
String getValueB();
void setValueB(String valueB);
}
public interface BaseC extends Root
{
String getValueC();
void setValueC(String valueC);
}
public final class ImplA implements BaseA
{
private String id;
private String description;
private String valueA;
private ImplA() { }
public static ImplABuilder builder()
{
return new ImplABuilder(new ImplA());
}
private static class ImplABuilder extends BaseABuilder<ImplABuilder, ImplA> // assuming ImplA is final
{
ImplABuilder(ImplA object)
{
super(object);
}
// additional methods for ImplA class
}
}
I am trying to use inheritence and generics to create my application, but it doesn't seem to work the way I expect it to. I'll show you what I mean (TL;DR at the bottom):
public interface IModel extends Serializable {
public int save();
public void update();
public void delete();
}
// <T> is a JPA annotated entity/class
#SuppressWarnings("serial")
public abstract class Model<T> implements IModel {
private final Repository<T> _repository;
protected T _entity;
public Model(T entity, Repository<T> repository) {
this._entity = entity;
this._repository = repository;
}
public int save() {
return _repository.save(_entity);
}
...
}
This is implemented in for example my AccountModel, which is a Model with generic Account (which is a JPA entity) and which implements IAccount.
public class AccountModel extends Model<Account> implements IAccount {
private static final AccountRepository REPOSITORY = new AccountRepository();
public AccountModel(Account entity) {
super(entity, REPOSITORY);
}
// Method implementations...
}
My generic Repository looks like this:
public abstract class Repository<T> implements Serializable {
private static SessionFactory SESSION_FACTORY;
private final Class<T> _repositoryClass;
private static boolean _initiated = false;
public Repository(Class<T> repositoryClass) {
if (!Repository._initiated)
setup();
this._repositoryClass = repositoryClass;
}
private void setup() {
// logics
Repository._initiated = true;
}
public final Model<T> getById(int id) {
Session session = SESSION_FACTORY.openSession();
try {
session.beginTransaction();
T t = session.get(_repositoryClass, id);
return new Model<T>(t, this); // As suggested by #Vlad
}
finally {
session.close();
}
}
}
The account implementation of this abstract Repository is:
public class AccountRepository extends Repository<Account> {
public AccountRepository() {
super(Account.class);
}
public Model<Account> getByEmail(String emailAddress) {...}
}
So far so good, this is all working as expected. But I cannot use a Model<T> as a TModel.
TL;DR
I would like use the following line of code:
AccountModel account = new AccountRepository().getById(1);
Since AccountModel inherits Model<Account> and new AccountRepository().getById() always returns Model<Account> I expect this to work, but it doesn't.
What am I missing?
problem
I want to create a class with a fluent builder, both of which can be inherited and extended. Base class should have all the common and mandatory fields, children should have different optional fields
simple example below (best, simplistic usecase I could come up with ;p)
base: Animal
name
age
static Builder
impl: Snake extends Animal
length
static Builder extends Animal.Builder
impl: Spider extends Animal
numberOfLegs
static Builder extends Animal.Builder
and I'd like to use it in one of those ways (most preferred one is the first one):
Spider elvis = Spider.name("elvis").age(1).numberOfLegs(8).build();
Spider elvis = Spider.builder().name("elvis").age(1).numberOfLegs(8).build();
Spider elvis = new Spider.Builder().name("elvis").age(1).numberOfLegs(8).build();
what I want to achieve is
user of this builder will have to provide some minimal information (so the system can work without problems), otherwise he won't be able to build that object
all the optional fields can be declared, with no particular order, after mandatory fields are there
it is possible that I'll need to add some mandatory fields for children, but that can be handled with ease by just changing the first method called in the builder
I don't want to have any casts outside those classes (here: in Main), but I don't mind them inside this code (here: in Animal or Spider)
so far I failed and I'd be very grateful if you could please help me find a way out of it :)
or maybe there is just a different approach that I should think about?
most valuable sources I used
http://blog.crisp.se/2013/10/09/perlundholm/another-builder-pattern-for-java
http://egalluzzo.blogspot.com/2010/06/using-inheritance-with-fluent.html
Generic fluent Builder in Java
work done so far
the code so far can be found below. there are some traces of the things I tried and failed, there are some unused or just weird stuff (best example is IBuildImpl). Those are left to give you an understanding of what I tried, but if you think that this needs moderation - please let me know and I'll clean them up
Base
package fafafa;
public abstract class Animal<T> {
String name; //mandatory field, one of many
Integer age; //mandatory field, one of many
public String getName() {
return name;
}
#Override
public String toString() {
return "Animal{" +
"name='" + name + '\'' +
", age='" + age + '\'' +
'}';
}
interface IName {
IAge name(String name);
}
interface IAge {
IBuild age(Integer age);
}
interface IBuild<T extends Animal<T>> {
T build();
}
public abstract static class Builder<T extends Animal<T>, B extends Builder<T, B>>
implements IName, IAge, IBuild<T> {
protected T objectBeingBuilt;
protected abstract B that();
protected abstract T createEmptyObject();
Builder(){
this.objectBeingBuilt = createEmptyObject();
System.out.println();
}
#Override
public IAge name(String name) {
objectBeingBuilt.name = name;
return that();
}
#Override
public IBuild age(Integer age) {
objectBeingBuilt.age = age;
return that();
}
// #Override
// public T build() {
// return objectBeingBuilt;
// }
}
}
Impl
package fafafa;
public class Spider extends Animal<Spider> {
Integer numberOfLegs; //optional field, one of many
private Spider() {
}
public Integer getNumberOfLegs() {
return numberOfLegs;
}
#Override
public String toString() {
return "Spider{" +
"numberOfLegs='" + numberOfLegs + '\'' +
"} " + super.toString();
}
// public static Builder<Spider, Builder> name(String name) {
// return (Builder) new Builder().name(name);
// }
interface INumberOfLegs {
IBuild numberOfLegs(Integer numberOfLegs);
}
interface IBuildImpl extends IBuild<Spider>, INumberOfLegs {
#Override
Spider build();
}
public static class Builder extends Animal.Builder<Spider, Builder> implements IBuildImpl {
#Override
protected Builder that() {
return this;
}
#Override
protected Spider createEmptyObject() {
return new Spider();
}
public IBuild numberOfLegs(Integer numberOfLegs) {
objectBeingBuilt.numberOfLegs = numberOfLegs;
return that();
}
public Spider build() {
return objectBeingBuilt;
}
}
}
Main
package fafafa;
public class Main {
public static void main(String[] args) {
Spider build = new Spider.Builder().name("elvis")
.age(1)
.numberOfLegs(8) //cannot resolve method numberOfLegs
.build();
System.out.println(build);
}
}
Looks like to many generics in a code, I've tried to simplify it a little.
Animal
package come.stackoverflow.builder;
public abstract class Animal {
private final String name; //mandatory field, one of many
private final Integer age; //mandatory field, one of many
Animal(final String name, final Integer age) {this.name = name; this.age = age;}
public String getName() {return name;}
public Integer getAge() {return age;}
#Override public String toString() {return String.format("Animal {name='%s', age='%s'}'", name, age);}
interface IBuild<T> {
T build();
}
public abstract static class AnimalBuilder<B extends AnimalBuilder, T extends Animal> implements IBuild<T> {
String name;
Integer age;
public B name(final String name) {this.name = name; return (B) this;}
public B age(final Integer age) {this.age = age; return (B) this;}
}
}
Spider
package come.stackoverflow.builder;
public class Spider extends Animal {
private final Integer numberOfLegs; //optional field, one of many
private Spider(final String name, final Integer age, final Integer numberOfLegs) {super(name, age); this.numberOfLegs = numberOfLegs;}
public Integer getNumberOfLegs() {return numberOfLegs;}
#Override public String toString() {return String.format("Spider {numberOfLegs='%s'}, %s", getNumberOfLegs(), super.toString());}
public static class SpiderBuilder extends AnimalBuilder<SpiderBuilder, Spider> {
Integer numberOfLegs;
public SpiderBuilder numberOfLegs(final Integer numberOfLegs) {this.numberOfLegs = numberOfLegs; return this;}
public Spider build() {return new Spider(name, age, numberOfLegs);}
}
}
Main Test
import come.stackoverflow.builder.Spider;
public class Main {
public static void main(String[] args) {
Spider build = new Spider.SpiderBuilder()
.name("elvis").numberOfLegs(8).age(1)
.build();
System.out.println(build);
}
}
Execution Result:
Spider {numberOfLegs='8'}, Animal {name='elvis', age='1'}'
The problem of your code is the interface:
interface IAge {
IBuild age(Integer age);
}
This will always return the basic IBuild interface with no parameter, no matter, if the implementation implements it with some argument. Actually even returning it with the parameter wouldn't extend the builder with additional methods.
The parameter in the builder needs to be the extended builder, and not the type to be built.
All interfaces for the common parameters need to be parametrized with it to allow propper continuation.
Here is a suggestion:
1. Don't use IName interface. Replace it with static entry method of the builder
2. Parametrize IAge interface
3. No common builder needed. It can be replaced with inline lambda implementation
Here is the code:
#FunctionalInterface
public interface IAge<B> {
B age(Integer age);
}
public class AnimalBuilder implements IBuild<Animal> {
private final String name;
private final Integer age;
private Integer numberOfLegs;
private AnimalBuilder(String name, Integer age) {
this.name = name;
this.age = age;
}
// Builder entry method
public static IAge<AnimalBuilder> name(String name) {
return age -> new AnimalBuilder(name, age);
}
public AnimalBuilder numberOfLegs(int value) {
numberOfLegs = value;
return this;
}
#Override
public Animal build() {
return new Animal(name, age, numberOfLegs);
}
}
This allows following usage:
AnimalBuilder.name("elvis").age(1).numberOfLegs(8).build();
The problem is in the abstract builder :
public abstract static class Builder<T extends Animal<T>, B extends Builder<T, B>>
implements IName, IAge, IBuild<T> {
...
#Override
public IAge name(String name) {
objectBeingBuilt.name = name;
return that();
}
#Override
public IBuild age(Integer age) {
objectBeingBuilt.age = age;
return that();
}
So, all your concrete builders return the same IBuild<T> interface when you invoke the age() method.
and as you see :
interface IBuild<T extends Animal<T>> {
T build();
}
this interface doesn't allow to return a object where you have methods to set properties with your builder.
When you invoke the name() method, you also don't get the builder :
interface IAge {
IBuild age(Integer age);
}
You should declare age() and name() in the abstract builder like that :
public abstract static class Builder<T extends Animal<T>, B extends Builder<T, B>>{
...
public B name(String name) {
objectBeingBuilt.name = name;
return that();
}
public B age(Integer age) {
objectBeingBuilt.age = age;
return that();
}
In this way, at the compile time, the concrete builder will return the builder of the animal you are creating when you will invokebuilder.age(..).
Besides, I don't understand why having a builder interface for name and another one for age. What is interest to handle IAge and IName interfaces ?
It seems a too low level information to be useful in your builder.
Why not simply declaring you base builder like that :
public abstract static class Builder<T extends Animal<T>, B extends Builder<T, B>>
implements IBuild<T> {
protected T objectBeingBuilt;
protected abstract B that();
protected abstract T createEmptyObject();
Builder(){
this.objectBeingBuilt = createEmptyObject();
System.out.println();
}
public B name(String name) {
objectBeingBuilt.name = name;
return that();
}
public B age(Integer age) {
objectBeingBuilt.age = age;
return that();
}
}
I have not tested the code.