Skip to content

tomasbjerre/java-method-invocation-builder

Repository files navigation

Java Method Invocation Builder Build Status Maven Central

This is a Java library that enables automatic generation of builders at compile time. Builders used for invoking methods on instantiated objects. It enables default values of method parameters and is making the invocations readable.

It does not solve the same problem as Immutables or POJOBuilder. They are generating builders for creating instances of types. This is about invoking methods on previously instantiated types.

Sometimes you are forced to invoke methods that take alot of parameters. This makes the invoking code dirty and hard to read. The problem may be solved with a builder. The builder can have default values for each parameter and when you want to call the method, you just supply the parameters you want to change. This library automates the creation of such builders.

There is a Gradle example here.

There is a Maven example here.

There are some examples here that generates these builders.

Configuraion

You may configure the code generator to create variations of the builders.

  • @GenerateMethodInvocationBuilder(style=SUPPLY_INSTANCE_AS_INVOKE_PARAMETER) will add an invoke(instance) method.
  • @GenerateMethodInvocationBuilder(style=SUPPLY_INSTANCE_WITH_ON_METHOD) will add an on(instance) and invoke() method.
  • @GenerateMethodInvocationBuilder(style=SUPPLY_INSTANCE_IN_CONSTRUCTOR) will add an instance parameter to the constructor of the builder and invoke() method.

Examples

Here is one small example to quickly show what the tool does. And one, bigger, example that is the real use case that gave the idea to the tool.

Example 1

The repo includes examples of how to setup Maven and/or Gradle to do annotation processing. Aside from that you need to annotate the code that should have builders generated.

The library adds the @GenerateMethodInvocationBuilder and @Default annotations. They can be added to interfaces or classes.

@GenerateMethodInvocationBuilder
public class CarService {
 public CarService() {
 }

 public String getCarsByFilter(//
   @Default("Color.BLUE") Color color, //
   @Default("new ProductionYear(2001)") ProductionYear productionYear,//
   @Default("Tomas") String owner//
 ) {
  return "Filtering... " + color + productionYear + owner;
 }
}

A builder will be generated so that you can do this:

 CarService instance = new CarService();
 String carsByFilter = CarServiceGetCarsByFilterBuilder.getCarsByFilter()//
  .invoke(instance);

To invoke it with Blue, 2001 and Tomas. Or set any of the default values to something else:

 CarService instance = new CarService();
 String carsByFilter = CarServiceGetCarsByFilterBuilder.getCarsByFilter()//
  .withColor(Color.YELLOW)//
  .invoke(instance);

In this case the CarService is simply new:ed. But it may also be an interface.

@GenerateMethodInvocationBuilder
public interface CarService {
 String getCarsByFilter(//
   @Default("Color.BLUE") Color color, //
   @Default("new ProductionYear(2001)") ProductionYear productionYear,//
   @Default("Tomas") String owner//
 );
}

And perhaps you don't even have access to the implementation.

public class CarServiceUser {
 @Inject
 private CarServie carService;

 public String someMethod() {
  return CarServiceGetCarsByFilterBuilder.getCarsByFilter()//
   .withColor(Color.YELLOW)//
   .invoke(instance);
 }
}

Example 2

This is the original use case that triggered me to start working with this project. Note that this project has actually nothing to do with Retrofit or REST services at all. It can be used on any class, or interface, instance.

I am using Retrofit to create a client for BitBucket Server. That project is hosted here. Here is the interface that specifies the pullrequests REST resource.

public interface BitBucketServerService {
 @GET("/rest/api/1.0/projects/{projectkey}/repos/{repositoryslug}/pull-requests?direction={direction}&at={at}&state={state}&order={order}&withattributes={withattributes}&withproperties={withproperties}")
 Call<BitbucketServerResponse<BitBucketServerPullRequest>> pullRequests(//
   @Query("projectkey") String projectKey,//
   @Query("repositoryslug") String repositoryslug,//
   @Query("direction") String direction,//
   @Query("at") Integer at,//
   @Query("state") String state,//
   @Query("order") String order,//
   @Query("withattributes") String withattributes,//
   @Query("withproperties") String withproperties);
}

When invoking that method without this library it would look something like this.

bitBucketServerService.pullRequests("PROJ","REPO","INCOMING","23","OPEN","NEWEST","true","true");
bitBucketServerService.pullRequests("PROJ","REPO","INCOMING","24","OPEN","NEWEST","true","true");
bitBucketServerService.pullRequests("PROJ","REPO","INCOMING","25","OPEN","NEWEST","true","true");

This library provides the @GenerateMethodInvocationBuilder annotation that can be added to a type like this.

@GenerateMethodInvocationBuilder
public interface BitBucketServerService {
 @GET("/rest/api/1.0/projects/{projectkey}/repos/{repositoryslug}/pull-requests?direction={direction}&at={at}&state={state}&order={order}&withattributes={withattributes}&withproperties={withproperties}")
 Call<BitbucketServerResponse<BitBucketServerPullRequest>> pullRequests(//
   @Default("PROJ") @Query("projectkey") String projectKey,//
   @Default("REPO") @Query("repositoryslug") String repositoryslug,//
   @Default("INCOMING") @Query("direction") String direction,//
   @Default("23") @Query("at") String at,//
   @Default("OPEN") @Query("state") String state,//
   @Default("NEWEST") @Query("order") String order,//
   @Default("true") @Query("withattributes") String withattributes,//
   @Default("true") @Query("withproperties") String withproperties);
}

A builder is automatically generated and we can do.

BitBucketServerServicePullRequestsBuilder.pullRequests()
 .invoke(bitBucketServerService);

BitBucketServerServicePullRequestsBuilder.pullRequests()
 .withAt("24")
 .invoke(bitBucketServerService);

BitBucketServerServicePullRequestsBuilder.pullRequests()
 .withAt("25")
 .invoke(bitBucketServerService);

About

Enables default values of method parameters in Java and is making the invocations readable.

Topics

Resources

License

Stars

Watchers

Forks

Sponsor this project

Packages

No packages published