mkarneim / pojobuilder

A Java Code Generator for Pojo Builders
Other
334 stars 44 forks source link

Generate builders for external POJOs #169

Closed lbovet closed 3 years ago

lbovet commented 3 years ago

I wish we could generate builders for POJOs that do not belong to the project, e.g. from libraries. What we can do today is subclass the external class:

@PojoBuilder
public class MyBasicDataSource extends BasicDataSource {
}

Which adds naming overhead and do not work in all cases (final classes, generics, ...). Could we think about a way to choose the POJO class like:

@PojoBuilder(withPojoClass = DataSource.class)
class MyBasicDataSource extends BasicDataSource {
}

It may be a bit weird since the MyBasicDataSource class is compiled but never used as such (hence package protected). However, this solution is quite easy to add to the existing codebase. Would you welcome a PR?

mkarneim commented 3 years ago

Hi Laurent!

Thank you for your suggestion.

Do you know that by annotating a factory method you already can trigger the generation of builders for classes from external libraries?

lbovet commented 3 years ago

Yes, but you have to code all by yourself... I'll have a look in the code if I can contribute that.

drekbour commented 3 years ago

@lbovet You need to explain the end solution you were expecting to see. PB needs to know which classes (and constructors etc) to use; Factory-method support let's it do exactly that without subclassing.

It does, however, require repetition of all constructor-args in the factory method. Perhaps you are looking for something more akin to Jackson's Mixins which allow you "pretend" the target class has @PojoBuilder annotation?

lbovet commented 3 years ago

That's precisely the repetition of all fields that I would like to avoid. Like it is the case when we annotate a project class and the setters are taken in account. Could we annotated a factory method in an interface without parameters and this would generate a builder using the setters?

public interface BasicDataSourceFactory {
  @GeneratePojoBuilder(withName="BasicDataSourceBuilder", intoPackage = "samples")
  BasicDataSource createDataSource();
}

It just discovers the setters of the class class and generate the builder accordingly. So we can use it as:

DataSource = new BasicDataSourceBuilder()
  .withDriverClassName("oracle.jdbc.driver.OracleDriver")
  .withUsername("scott")
  .withPassword("tiger")
  .withUrl(connectURI)
  .build()
drekbour commented 3 years ago

factory method ... generate a builder using the setters

From memory, it should do this already. Simply make the factory-method return the vanilla new BasicDataSource() and the builder should include all "visible" setters...

lbovet commented 3 years ago

Ouch, did not though about trying that. I just checked it works as you said. The documentation let us think that the constructor arguments are mandatory. That's great! Many thanks.