On Tue, 15 Jan 2019 at 07:48, Alan Bateman <alan.bate...@oracle.com> wrote:
> Which library or framework is this and is there a write-up of the issues > encountered when migrating it to use Lookup objects? > > -Alan > It is a small dependency injection/application I am trying to built on top of the module system. It is not in finished form yet, however, I have made some notes about some observations I've done. # Naming / User Friendliness I know this is to late to change, but I think the Lookup mechanism could have been designed a bit more user friendly. Here is a simple method that lets a user construct a new object using dependency injection. The two parameters are: The type of object that should be constructed, and a Lookup object that can be used by the underlying framework for invoking a constructor on the specified type. import java.lang.invoke.MethodHandles; public <T> inject(Class<T> type, MethodHandles.Lookup lookup) Having Lookup defined as a static nested class of MethodHandles kind of requires you to introduce two topics at the same time. It is quite a bit to explain if you only have 10 lines for a getting started guide. Especially since the usage of both of them are more or less unknown to 99% of Java developers. I could use this signature import java.lang.invoke.MethodHandles.Lookup; public <T> inject(Class<T> type, Lookup lookup) But unless you know how to acquire a lookup object, it is a bit hard to figure out you need to look in its parent object to find the method. Buried, among tons of other methods. I think adding a static method such as Lookup.of() could make it a bit less painful. Its still a bit difficult to explain why this is needed without getting to technical. But I hope this will change if it sees widespread use. # Single Module In general, Lookup objects are really easy to work with when you are have a _single_ module that has a dependency on a library that needs a Lookup object to be initialized. And you are in full control of initializing the library. # Inversion of Control/Container deployment Here I am thinking about something like how people would normally deploy a modern servlet WAR; A bunch of annotated classes packaged in a single jar. Since your code is being initialized by the container you cannot directly handoff a Lookup object to the container. Instead you need to rely on some kind of delivery mechanism. For example, by requiring all deployable bundles to provide a service (that secretly exposes the Lookup object) via a ServiceLoader to the container. However, this quickly gets complicated because if you work with something like Jakarte EE, where you have to provide a standardized mechanism. With which any implementor can get a hold of the provided lookup object. But at the same time make sure no one else can read it. This is an issue with qualified open statements via module-info as well. If you do not know which implementation you are going to deploy your WAR in. You cannot use a qualified open statement. So you are left with "open module", which I suspect will be how things are going to work for a long time. Some of these issues might be solvable by using something like Module layers. # Multiple Modules If your application consists of multiple modules. For example, you might have some customer-services in one module and some order-service in a another module. Then a third module that kind of glues the two modules together. You might also have a DI framework, a JPA implementation and a JaxRS container. It is a bit of similar problem here, you need to handoff a Lookup object from customer-services->main module and from order-services->main module. And then the main module then needs to initialize each library with each of the Lookup objects for every module. You also sometimes get into some complex situations where an abstract class is located in one module, and the concrete class in another module. Each of them having an annotated method/field that you need to access. So you need one Lookup object to access the method on the abstract class and another Lookup object to access the method on the concrete class. Depending on how you track your Loookup objects, you worst case end of with API's like this public <T> inject(Class<T> type, MethodHandles.Lookup... lookup) and then some complex logic to match methods with Lookup objects. I actually really like working with Lookup objects. However, I think it potentially could end up with a lot of micro management for larger projects. And then people are going to be, fine, lets just put open module everywhere. /Kasper