Background: I want to instrument all implementations of a set of interfaces (within the same package) with a LogInterceptor (just logging that the method was called). Therefore I wrote a javaagent with byte-buddy. In general that is working fine, but I'm struggling with finding all implementations of a set of interfaces.
Assume we have a set of Java interfaces in a package my.company.api, then I tried it the following way:
public static void premain(String arguments, Instrumentation instrumentation) {
new AgentBuilder.Default()
.ignore(ElementMatchers.isInterface())
.ignore(ElementMatchers.isEnum())
.type(ElementMatchers.nameMatches("my\\.company\\.api\\..*"))
.transform(new AgentBuilder.Transformer() {
#Override
public DynamicType.Builder transform(DynamicType.Builder builder, TypeDescription typeDescription, ClassLoader classloader) {
return builder
.method(ElementMatchers.isPublic())
.intercept(MethodDelegation.to(LogInterceptor.class));
}
}).installOn(instrumentation);
}
I am quite new with byte-buddy, maybe someone can give me a hint what I am doing wrong.
First of all, you are not chaining the ignore matchers correctly; it should be:
.ignore(isInterface().or(isEnum()))
As for matching the interfaces, you can try the hasSuperType matcher. If you try to match interfaces of a given package, you might try:
hasSuperType(nameStartsWith("my.company.api.").and(isInterface()))
Using a prefix matcher is much more efficient compared to a regex.
Related
I am using bytebuddy to instrument method calls in tests. I am running into this issue:
Agent Error: java.lang.AbstractMethodError: Receiver class nz.ac.wgtn.nullannoinference.agent.NullLoggerAgent$4 does not define or inherit an implementation of the resolved method abstract transform(Lnet/bytebuddy/dynamic/DynamicType$Builder;Lnet/bytebuddy/description/type/TypeDescription;Ljava/lang/ClassLoader;Lnet/bytebuddy/utility/JavaModule;Ljava/security/ProtectionDomain;)Lnet/bytebuddy/dynamic/DynamicType$Builder; of interface net.bytebuddy.agent.builder.AgentBuilder$Transformer.
The critical issue is the last parameter of AgentBuilder$Transformer::transform of type ProtectionDomain. In version 1.10.20 this is abscent. I could upgrade but this does not solve my issue as I cannot control the version of bytebuddy being used as many of the programs I want to instrument already have a bytebuddy dependency through mockito, often a slightly older version.
Perhaps shading could work. Any advise how to proceed here ? I could always write multiple versions of the agent for different versions of bytebuddy but this seems very clumsy, and a maintenance nightmare.
I think I have figured it out -- actually it is rather easy, I am so used to lambdas that I did not see the obvious. This seems to work:
new AgentBuilder.Default()
..
.transform(
new AgentBuilder.Transformer() {
public DynamicType.Builder<?> transform(DynamicType.Builder<?> builder, TypeDescription typeDescription, ClassLoader classLoader, JavaModule javaModule) {
return builder.visit(NullChecks.MethodWithoutReturnValues.VISITOR);
}
public DynamicType.Builder<?> transform(DynamicType.Builder<?> builder, TypeDescription typeDescription, ClassLoader classLoader, JavaModule javaModule,ProtectionDomain pd) {
return builder.visit(NullChecks.MethodWithoutReturnValues.VISITOR);
}
}
)
I.e. just overload transform to support the two API versions.
I have a BIG Android app that needs to run different code for depending on the OS version, the manufacturer, and many other things. This app however needs to be a single APK. It needs to be smart enough at runtime to determine which code to use. Until now we have been using Guice but performance issues are causing us to consider migrating to Dagger. However, I've been unable to determine if we can achieve the same use case.
The main goal is for us have some code that runs at startup to provide a list of compatible Modules. Then pass that this list to Dagger to wire everything up.
Here is some pseudocode of the current implementation in Guice we want to migrate
import com.google.inject.AbstractModule;
#Feature("Wifi")
public class WifiDefaultModule extends AbstractModule {
#Override
protected void configure() {
bind(WifiManager.class).to(WifiDefaultManager.class);
bind(WifiProcessor.class).to(WifiDefaultProcessor.class);
}
}
#Feature("Wifi")
#CompatibleWithMinOS(OS > 4.4)
class Wifi44Module extends WifiDefaultModule {
#Override
protected void configure() {
bind(WifiManager.class).to(Wifi44Manager.class);
bindProcessor();
}
#Override
protected void bindProcessor() {
(WifiProcessor.class).to(Wifi44Processor.class);
}
}
#Feature("Wifi")
#CompatibleWithMinOS(OS > 4.4)
#CompatibleWithManufacturer("samsung")
class WifiSamsung44Module extends Wifi44Module {
#Override
protected void bindProcessor() {
bind(WifiProcessor.class).to(SamsungWifiProcessor.class);
}
#Feature("NFC")
public class NfcDefaultModule extends AbstractModule {
#Override
protected void configure() {
bind(NfcManager.class).to(NfcDefaultManager.class);
}
}
#Feature("NFC")
#CompatibleWithMinOS(OS > 6.0)
class Nfc60Module extends NfcDefaultModule {
#Override
protected void configure() {
bind(NfcManager.class).to(Nfc60Manager.class);
}
}
public interface WifiManager {
//bunch of methods to implement
}
public interface WifiProcessor {
//bunch of methods to implement
}
public interface NfcManager {
//bunch of methods to implement
}
public class SuperModule extends AbstractModule {
private final List<Module> chosenModules = new ArrayList<Module>();
public void addModules(List<Module> features) {
chosenModules.addAll(features);
}
#Override
protected void configure() {
for (Module feature: chosenModules) {
feature.configure(binder())
}
}
}
so at startup the app does this:
SuperModule superModule = new SuperModule();
superModule.addModules(crazyBusinessLogic());
Injector injector = Guice.createInjector(Stage.PRODUCTION, superModule);
where crazyBusinessLogic() reads the annotations of all the modules and determines a single one to use for each feature based on device properties. For example:
a Samsung device with OS = 5.0 will have crazyBusinessLogic() return the list { new WifiSamsung44Module(), new NfcDefaultModule() }
a Samsung device with OS = 7.0 will have crazyBusinessLogic() return the list { new WifiSamsung44Module(), new Nfc60Module() }
a Nexus device with OS = 7.0 will have crazyBusinessLogic() return the list { new Wifi44Module(), new Nfc60Module() }
and so on....
Is there any way to do the same with Dagger? Dagger seems to require you to pass the list of modules in the Component annotation.
I read a blog that seems to work on a small demo, but it seems clunky and the extra if statement and extra interfaces for components might cause my code to balloon.
https://blog.davidmedenjak.com/android/2017/04/28/dagger-providing-different-implementations.html
Is there any way to just use a list of modules returned from a function like we are doing in Guice? If not, what would be the closest way that would minimize rewriting the annotations and the crazyBusinessLogic() method?
Dagger generates code at compile-time, so you are not going to have as much module flexibility as you did in Guice; instead of Guice being able to reflectively discover #Provides methods and run a reflective configure() method, Dagger is going to need to know how to create every implementation it may need at runtime, and it's going to need to know that at compile time. Consequently, there's no way to pass an arbitrary array of Modules and have Dagger correctly wire your graph; it defeats the compile-time checking and performance that Dagger was written to provide.
That said, you seem to be okay with a single APK containing all possible implementations, so the only matter is selecting between them at runtime. This is very possible in Dagger, and will probably fall into one of four solutions: David's component-dependencies-based solution, Module subclasses, stateful module instances, or #BindsInstance-based redirection.
Component dependencies
As in David's blog you linked, you can define an interface with a set of bindings that you need to pass in, and then supply those bindings through an implementation of that interface passed into the builder. Though the structure of the interface makes this well-designed to pass Dagger #Component implementations into other Dagger #Component implementations, the interface may be implemented by anything.
However, I'm not sure this solution suits you well: This structure is also best for inheriting freestanding implementations, rather than in your case where your various WifiManager implementations all have dependencies that your graph needs to satisfy. You might be drawn to this type of solution if you need to support a "plugin" architecture, or if your Dagger graph is so huge that a single graph shouldn't contain all of the classes in your app, but unless you have those constraints you may find this solution verbose and restrictive.
Module subclasses
Dagger allows for non-final modules, and allows for the passing of instances into modules, so you can simulate the approach you have by passing subclasses of your modules into the Builder of your Component. Because the ability to substitute/override implementations is frequently associated with testing, this is described on the Dagger 2 Testing page under the heading "Option 1: Override bindings by subclassing modules (don’t do this!)"—it clearly describes the caveats of this approach, notably that the virtual method call will be slower than a static #Provides method, and that any overridden #Provides methods will necessarily need to take all parameters that any implementation uses.
// Your base Module
#Module public class WifiModule {
#Provides WifiManager provideWifiManager(Dep1 dep1, Dep2 dep2) {
/* abstract would be better, but abstract methods usually power
* #Binds, #BindsOptionalOf, and other declarative methods, so
* Dagger doesn't allow abstract #Provides methods. */
throw new UnsupportedOperationException();
}
}
// Your Samsung Wifi module
#Module public class SamsungWifiModule {
#Override WifiManager provideWifiManager(Dep1 dep1, Dep2 dep2) {
return new SamsungWifiManager(dep1); // Dep2 unused
}
}
// Your Huawei Wifi module
#Module public class HuaweiWifiModule {
#Override WifiManager provideWifiManager(Dep1 dep1, Dep2 dep2) {
return new HuaweiWifiManager(dep1, dep2);
}
}
// To create your Component
YourAppComponent component = YourAppComponent.builder()
.baseWifiModule(new SamsungWifiModule()) // or name it anything
// via #Component.Builder
.build();
This works, as you can supply a single Module instance and treat it as an abstract factory pattern, but by calling new unnecessarily, you're not using Dagger to its full potential. Furthermore, the need to maintain a full list of all possible dependencies may make this more trouble than it's worth, especially given that you want all dependencies to ship in the same APK. (This might be a lighter-weight alternative if you need certain kinds of plugin architecture, or you want to avoid shipping an implementation entirely based on compile-time flags or conditions.)
Module instances
The ability to supply a possibly-virtual Module was really meant more for passing module instances with constructor arguments, which you could then use for choosing between implementations.
// Your NFC module
#Module public class NfcModule {
private final boolean useNfc60;
public NfcModule(boolean useNfc60) { this.useNfc60 = useNfc60; }
#Override NfcManager provideNfcManager() {
if (useNfc60) {
return new Nfc60Manager();
}
return new NfcDefaultManager();
}
}
// To create your Component
YourAppComponent component = YourAppComponent.builder()
.nfcModule(new NfcModule(true)) // again, customize with #Component.Builder
.build();
Again, this doesn't use Dagger to its fullest potential; you can do that by manually delegating to the right Provider you want.
// Your NFC module
#Module public class NfcModule {
private final boolean useNfc60;
public NfcModule(boolean useNfc60) { this.useNfc60 = useNfc60; }
#Override NfcManager provideNfcManager(
Provider<Nfc60Manager> nfc60Provider,
Provider<NfcDefaultManager> nfcDefaultProvider) {
if (useNfc60) {
return nfc60Provider.get();
}
return nfcDefaultProvider.get();
}
}
Better! Now you don't create any instances unless you need them, and Nfc60Manager and NfcDefaultManager can take arbitrary parameters that Dagger supplies. This leads to the fourth solution:
Inject the configuration
// Your NFC module
#Module public abstract class NfcModule {
#Provides static NfcManager provideNfcManager(
YourConfiguration yourConfiguration,
Provider<Nfc60Manager> nfc60Provider,
Provider<NfcDefaultManager> nfcDefaultProvider) {
if (yourConfiguration.useNfc60()) {
return nfc60Provider.get();
}
return nfcDefaultProvider.get();
}
}
// To create your Component
YourAppComponent component = YourAppComponent.builder()
// Use #Component.Builder and #BindsInstance to make this easy
.yourConfiguration(getConfigFromBusinessLogic())
.build();
This way you can encapsulate your business logic in your own configuration object, let Dagger provide your required methods, and go back to abstract modules with static #Provides for the best performance. Furthermore, you don't need to use Dagger #Module instances for your API, which hides implementation details and makes it easier to move away from Dagger later if your needs change. For your case, I recommend this solution; it'll take some restructuring, but I think you'll wind up with a clearer structure.
Side note about Guice Module#configure(Binder)
It's not idiomatic to call feature.configure(binder()); please use install(feature); instead. This allows Guice to better describe where errors occur in your code, discover #Provides methods in your Modules, and to de-duplicate your module instances in case a module is installed more than once.
Is there any way to just use a list of modules returned from a
function like we are doing in Guice? If not, what would be the closest
way that would minimize rewriting the annotations and the
crazyBusinessLogic() method?
Not sure this is the answer you're looking for, but just in case you do have other options and for other community members I will describe completely different approach.
I would say that the way you used Guice until now is an abuse of DI framework, and you will be much better off leveraging this opportunity to remove this abuse instead of implementing it in Dagger.
Let me explain.
The main goal of dependency injection architectural pattern is to have construction logic segregated from functional logic.
What you basically want to achieve is standard polymorphism - provide different implementations based on a set of parameters.
If you use Modules and Components for that purpose, you will end up structuring your DI code according to business rules governing the need for these polymorphic implementations.
Not only will this approach requires much more boilerplate, but it also prevents emergence of cohesive Modules that have meaningful structure and provide insights into application's design and architecture.
In addition, I doubt you will be able to unit test these business rules "encoded" inside dependency injection logic.
There are two approaches which are much better IMHO.
First approach is still not very clean, but, at least, it doesn't compromise the large scale structure of dependency injection code:
#Provides
WifiManager wifiManager(DeviceInfoProvider deviceInfoProvider) {
if (deviceInfoProvider.isPostKitKat() ) {
if (deviceInfoProvider.isSamsung()) {
return new WifiMinagerSamsungPostKitKat();
} else {
return new WifiMinagerPostKitKat();
}
} else {
return new WifiMinagerPreKitKat();
}
}
The logic that chooses between implementation still resides in DI code, but, at least, it did not make it into the large scale structure of that part.
But the best solution in this case is to make a proper object oriented design, instead of abusing DI framework.
I'm pretty sure that the source code of all these classes is very similar. They might even inherit from one another while overriding just one single method.
In this case, the right approach is not duplication/inheritance, but composition using Strategy design pattern.
You would extract the "strategy" part into a standalone hierarchy of classes, and define a factory class that constructs them based on system's parameters. Then, you could do it like this:
#Provides
WiFiStrategyFactory wiFiStrategyFactory(DeviceInfoProvider deviceInfoProvider) {
return new WiFiStrategyFactory(deviceInfoProvider);
}
#Provides
WifiManager wifiManager(WiFiStrategyFactory wiFiStrategyFactory) {
return new WifiMinager(WiFiStrategyFactory.newWiFiStrategy());
}
Now construction logic is simple and clear. The differentiation between strategies encapsulated inside WiFiStrategyFactory and can be unit tested.
The best part of this proper approach is that when a new strategy will need to be implemented (because we all know that Android fragmentation is unpredictable), you won't need to implement new Modules and Components, or make any changes to DI structure. This new requirement will be handled by just providing yet another implementation of the strategy and adding the instantiation logic to the factory.
All that while being kept safe with unit tests.
I'm currently using IAnnotationTransformer to exclude all tests listed in an XML which contain a particular string in their name, for example:
#Override
#SuppressWarnings("rawtypes")
public void transform(ITestAnnotation annotation, Class testClass, Constructor testConstructor, Method testMethod) {
if(testMethod.getName().contains("StringGoesHere")){
annotation.setEnabled(false);
}
This works perfectly well, however due to the naming convention of my tests, and the vast amount of tests which I need to exclude, the ideal solution would be to find a way to exclude the test if it calls upon a particular method. For example, I want to exclude all tests which call upon the method .clickUserSettings() shown below:
#Test
public void editUserDetailsOnStackOverflow() {
final StackOverflow so = stackOverflow.loginAsMe()
.clickUserSettings()
.changeUserEmail()
.clickSave()
.assertChangeSuccessful();
}
Does anyone know how I might be able to achieve this? I feel like I've explored all other avenues (classes, packages, testMethods, groups, xml, etc) And the reason it has to be done in this way is because I currently have 40,000 tests (15,000 of which will likely be excluded depending on the browserMode variable set by the tester) This is the general idea I was hoping to achieve:
#Override
#SuppressWarnings("rawtypes")
public void transform(ITestAnnotation annotation, Class testClass, Constructor testConstructor, Method testMethod) {
if(testMethod.getAllCalledMethods.contains(".clickUserSettings()")){
annotation.setEnabled(false);
}
If this can be done it will solve my issue,
Cheers
This is not possible with TestNG. TestNG has visibility only to the methods that are annotated with its annotations and its not aware of the code path that a TestNG method traverses during its course of execution. [ Here I am assuming that the method clickUserSettings() is a utility method that your #Test methods perhaps call into, as part of its execution ]
So you have a couple of options
Resort to using groups wherein all methods that call into clickUserSettings() as part of a particular group and then exclude that group from execution.
Create your own custom annotation, annotate all methods that invoke clickUserSettings() using this annotation, and then modify your current AnnotationTransformer to look for this annotation at either the method level or at the class level.
Can I do it with reflection or something like that?
I have been searching for a while and there seems to be different approaches, here is a summary:
reflections library is pretty popular if u don't mind adding the dependency. It would look like this:
Reflections reflections = new Reflections("firstdeveloper.examples.reflections");
Set<Class<? extends Pet>> classes = reflections.getSubTypesOf(Pet.class);
ServiceLoader (as per erickson answer) and it would look like this:
ServiceLoader<Pet> loader = ServiceLoader.load(Pet.class);
for (Pet implClass : loader) {
System.out.println(implClass.getClass().getSimpleName()); // prints Dog, Cat
}
Note that for this to work you need to define Petas a ServiceProviderInterface (SPI) and declare its implementations. you do that by creating a file in resources/META-INF/services with the name examples.reflections.Pet and declare all implementations of Pet in it
examples.reflections.Dog
examples.reflections.Cat
package-level annotation. here is an example:
Package[] packages = Package.getPackages();
for (Package p : packages) {
MyPackageAnnotation annotation = p.getAnnotation(MyPackageAnnotation.class);
if (annotation != null) {
Class<?>[] implementations = annotation.implementationsOfPet();
for (Class<?> impl : implementations) {
System.out.println(impl.getSimpleName());
}
}
}
and the annotation definition:
#Retention(RetentionPolicy.RUNTIME)
#Target(ElementType.PACKAGE)
public #interface MyPackageAnnotation {
Class<?>[] implementationsOfPet() default {};
}
and you must declare the package-level annotation in a file named package-info.java inside that package. here are sample contents:
#MyPackageAnnotation(implementationsOfPet = {Dog.class, Cat.class})
package examples.reflections;
Note that only packages that are known to the ClassLoader at that time will be loaded by a call to Package.getPackages().
In addition, there are other approaches based on URLClassLoader that will always be limited to classes that have been already loaded, Unless you do a directory-based search.
What erickson said, but if you still want to do it then take a look at Reflections. From their page:
Using Reflections you can query your metadata for:
get all subtypes of some type
get all types annotated with some annotation
get all types annotated with some annotation, including annotation parameters matching
get all methods annotated with some
In general, it's expensive to do this. To use reflection, the class has to be loaded. If you want to load every class available on the classpath, that will take time and memory, and isn't recommended.
If you want to avoid this, you'd need to implement your own class file parser that operated more efficiently, instead of reflection. A byte code engineering library may help with this approach.
The Service Provider mechanism is the conventional means to enumerate implementations of a pluggable service, and has become more established with the introduction of Project Jigsaw (modules) in Java 9. Use the ServiceLoader in Java 6, or implement your own in earlier versions. I provided an example in another answer.
Spring has a pretty simple way to acheive this:
public interface ITask {
void doStuff();
}
#Component
public class MyTask implements ITask {
public void doStuff(){}
}
Then you can autowire a list of type ITask and Spring will populate it with all implementations:
#Service
public class TaskService {
#Autowired
private List<ITask> tasks;
}
The most robust mechanism for listing all classes that implement a given interface is currently ClassGraph, because it handles the widest possible array of classpath specification mechanisms, including the new JPMS module system. (I am the author.)
try (ScanResult scanResult = new ClassGraph().whitelistPackages("x.y.z")
.enableClassInfo().scan()) {
for (ClassInfo ci : scanResult.getClassesImplementing("x.y.z.SomeInterface")) {
foundImplementingClass(ci); // Do something with the ClassInfo object
}
}
With ClassGraph it's pretty simple:
Groovy code to find implementations of my.package.MyInterface:
#Grab('io.github.classgraph:classgraph:4.6.18')
import io.github.classgraph.*
new ClassGraph().enableClassInfo().scan().withCloseable { scanResult ->
scanResult.getClassesImplementing('my.package.MyInterface').findAll{!it.abstract}*.name
}
What erikson said is best. Here's a related question and answer thread - http://www.velocityreviews.com/forums/t137693-find-all-implementing-classes-in-classpath.html
The Apache BCEL library allows you to read classes without loading them. I believe it will be faster because you should be able to skip the verification step. The other problem with loading all classes using the classloader is that you will suffer a huge memory impact as well as inadvertently run any static code blocks which you probably do not want to do.
The Apache BCEL library link - http://jakarta.apache.org/bcel/
Yes, the first step is to identify "all" the classes that you cared about. If you already have this information, you can enumerate through each of them and use instanceof to validate the relationship. A related article is here: https://web.archive.org/web/20100226233915/www.javaworld.com/javaworld/javatips/jw-javatip113.html
Also, if you are writing an IDE plugin (where what you are trying to do is relatively common), then the IDE typically offers you more efficient ways to access the class hierarchy of the current state of the user code.
I ran into the same issue. My solution was to use reflection to examine all of the methods in an ObjectFactory class, eliminating those that were not createXXX() methods returning an instance of one of my bound POJOs. Each class so discovered is added to a Class[] array, which was then passed to the JAXBContext instantiation call. This performs well, needing only to load the ObjectFactory class, which was about to be needed anyway. I only need to maintain the ObjectFactory class, a task either performed by hand (in my case, because I started with POJOs and used schemagen), or can be generated as needed by xjc. Either way, it is performant, simple, and effective.
A new version of #kaybee99's answer, but now returning what the user asks: the implementations...
Spring has a pretty simple way to acheive this:
public interface ITask {
void doStuff();
default ITask getImplementation() {
return this;
}
}
#Component
public class MyTask implements ITask {
public void doStuff(){}
}
Then you can autowire a list of type ITask and Spring will populate it with all implementations:
#Service
public class TaskService {
#Autowired(required = false)
private List<ITask> tasks;
if ( tasks != null)
for (ITask<?> taskImpl: tasks) {
taskImpl.doStuff();
}
}
I have 3 classes:
Error
ShellError
WebError
where
ShellError extends Error
and
WebError extends Error
In ShellError there are fields some of which are optional and others are required. I am building the object in the following manner:
shellError = new ShellError.Builder().setFile(filePattern)
.setHost(host).setPath(path).setSource(file.isSource())
.setJobName(p.getJobName()).build();
Since ShellError extends Error, I further:
shellError.setDescription(msg.toString());
shellError.setExceptionClass("MyEvilException");
shellError.setExceptionMessage("Some clever error message");
shellError.setStacktrace(stack);
So ... why bother with Builder? I like the fact that my build() amongst other things conveniently validates that all fields are set appropriately etc.
I would love it if I could .. build() ShellError and add to it the fields from the Error class.
What i did works.
The question is:
Is there a better way, or does it make sense what I did?
-- EDIT
I updated Builder() to accept some of the parameters which were in Error class before. Now I have
shellError = new ShellError.Builder(exception, "Some description").setFile(filePattern).setHost(host)
.setPath(path).setSource(file.isSource()).
setJobName(p.getJobName()).build();
What do you say? Better? Worse?
The builder pattern, popularized by Josh Bloch, has several benefits, but it doesn't work so elegantly on parent/subclasses, as explained in this discussion by our colleagues in the C# world. The best solution I have seen so far is this one (or a slight variant of it).
Based on the functions you've referenced, this is clearly not the standard java.lang.Error class. Typically builders are used to allow for an immutable object to be easily constructed or to provide functionality similar to "named parameters" in cases where there are lots of configuration / construction parameters.
For this particular case, it would be more sensible if the Error class were immutable after construction, and if these additional setter functions were on the builder instead of on the error class. I don't know how much control you have over any of these classes, but if you can modify them, I would suggest first making the builder support the same setters, so you can do all the configuration at the builder. Then, if it is feasible to do so, you could try removing these setter methods and instead allowing these to be configured from the constructor. If you don't have any control at all over those, you can could potentially extend the builder class with another one which supports these additional methods.
What you did makes sense. It seems like the design of the builder and error classes don't necessarily make a whole lot of sense, forcing you to write code that feels inelegant or inconsistent.
As it was already said, the builder pattern is not something that could organically fit into the existing Java object initialization politics. There are several approaches to achieve the required result. Though, of course, it is always better to avoid any ambiguous practices, it's not always possible. My hack is based on Java reflection API with generics:
abstract public class AbstractClass {
public static class Builder {
public <T extends AbstractClass> T build(Class<T> implementingClass) {
try {
Constructor<T> constructor = implementingClass
.getConstructor(new Class[]{Builder.class});
return constructor.newInstance(this);
} catch (NoSuchMethodException e) {
// TODO handle the exception
} catch (InvocationTargetException | InstantiationException |
IllegalAccessException e) {
// TODO handle the exception
}
}
}
protected AbstractClass(Builder builder) {
}
}
public class ImplementingClass extends AbstractClass {
public ImplementingClass (Builder builder) {
super(builder);
}
}
The initialization:
ImplementingClass instance = new AbstractClass.Builder()
.build(ImplementingClass.class);