Popularity
2.0
Declining
Activity
0.0
Stable
9
10
3

Description

After a longer time using differend DI-Frameworks I decided to start with an internal research project to explore the possibilities to write a different DI-Framework. Something that would fit better to my needs to work with old and big legacy projects. Based on the ProxyBuilder - www.proxybuilder.org that was born during the time I was writing the german Book "Dynamic Proxies" with Dr. Heinz Kabutz, I started to use this for the implementations of my first version of the Dynamic Dependency Injection project.

The goals I wanted to reach are: - as less as possible Binding Code - easy and simple Lifecycle - technical and business Model-Validation - easy debugging - easy mocking - Dynamic Context - only dependency to the JDK itself

Code Quality Rank: L4
Programming language: HTML
License: Apache License 2.0
Tags: Dependency Injection     Development     Java     Java 8     Proxy     CDI     DI     DDI    

Dynamic CDI alternatives and similar libraries

Based on the "Dependency Injection" category.
Alternatively, view Dynamic CDI alternatives based on common mentions on social networks and blogs.

Do you think we are missing an alternative of Dynamic CDI or a related project?

Add another 'Dependency Injection' Library

README

Welcome to the Project Dynamic CDI

Maven Central Codacy Badge

JDK Informations

Actual version is running from JDK8 up to JDK13. The version 1.0.x is based on JDK8.

The implementation is covered with over 90% mutation test coverage. The last report you can find under _docu/

[_docu/20180319/pit_overview.png](_docu/20180319/pit_overview.png)

How DDI will resolve the corresponding Implementation?

if you write @Inject Interface

1 ClassResolver means: 1 ClassResolver responsible for the given Interface. You can have n ClassResolver inside your classpath. But for every Interface only one that is responsible for it.

  • Interface , no Impl. -> Exception
  • Interface , no Impl., 1 Producer for the Interface -> Producer for the Interface will be used

  • Interface , 1 Impl. -> will use the Impl.

  • Interface , 1 Impl., 1 Producer for Impl. -> Producer for the Impl will be used

  • Interface , 1 Impl., n Producer for Impl. -> Exception

  • Interface , 1 Impl., 1 Producer for Interface -> Producer for the Interface will be used

  • Interface , 1 Impl., n Producer for Interface -> Exception

  • Interface , 1 Impl., 1 Producer for Interface , 1 Producer for Impl. -> Exception

  • Interface , n Impl. -> Exception

  • Interface , n Impl., 1 responsible ClassResolver -> result of the ClassResolver will be used

  • Interface , n Impl., 1 Producer for Interface -> Producer for the Interface will be used

  • Interface , n Impl., 1-n Producer for Impl. -> Exception

  • Interface , n Impl., 1 responsible ClassResolver, 1 Producer for Interface -> Producer for the Interface will be used

  • Interface , n Impl., 1 responsible ClassResolver, 1-n Producer for Impl. -> will use the resolved Class or corresponding Producer if available

  • Interface , n Impl., n responsible ClassResolver -> Exception

  • Interface, 1 Impl., n Producer for Impl, 1 ProducerResolver for Impl -> selected Producer from ProducerResolver

  • Interface, n Impl., 1 responsible ClassResolver, 0-n Producer for every Impl, 1 ProducerResolver for every Impl -> selected Producer from ProducerResolver, for selected Impl from ClassResolver

if you write @Inject Impl.

  • Impl. -> will use the Impl.
  • Impl., 1 Producer -> will use the Producer for the Impl.

How to write Mocks for Interfaces or classes ?

You can use this framework for the mocking too. The concept is based on the Designpattern ObjectAdapter. You can have too versions of an ObjectAdapter , based on the implementations the ProxyBuilder will give you. Version one is a DynamicObjectAdapter. This you could only use if you have an interface available. The DynamicObjectAdapterBuilder will be created during the compile phase if you annotate the corresponding interface with the Annotation @DynamicObjectAdapterBuilder. Please check the documentation about the DynamicObjectAdapter for more details.

Version two is a StaticObjectAdapter. This you could use for Interfaces and Classes. To create a StaticObjectAdapter for your target you have to annotate the the target class or interface with the Annotation @StaticObjectAdapter. After the compile phase you could find the generated classes at target/generated-sources (if you are using maven).

Mocking

If you want to use a Mock for an jUnitTest, you have to use a ClassResolver or ProducerResolver to make the decision for the Mock explicit for your test. The easiest way is the usage of an Producer that will create the Mock. With this you could mock something that is deep inside your system, without creating the full hierarchy with frameworks like Mockito. Mostly this will lead to constructions that are much more like the production system.

example with one interface and one production class

Inside the production source path you will have an interface and one implementation.

  public interface Service {
    String doWork(String txt);
  }

  public static class ServiceA implements Service {
    public String doWork(String txt) {
      return txt + "A";
    }
  }

During the runtime the solution is very simple, because there is only on implementation available. But now we would like to activate a Mock during the jUnit test. For this we need a second implementation called ServiceB

 public static class ServiceB implements Service {
    public String doWork(String txt) {
      return txt + "B";
    }
  }

To activate this mock only for the jUnit Tests we have to config the DI Container in a way that the ServiceB will be available. This means, during the startup phase @Before we are clearing the existing Reflection Model to make sure there is no other config from any other test anymore. After this we re activating only production classes and the package from the test itself.

  @Before
  public void setUp() throws Exception {
    DI.clearReflectionModel();
    DI.activatePackages("org.rapidpm");
    DI.activatePackages(this.getClass());
  }

Now we have the mock inside the reflection model, too. This means we have to give the container a possibility to resolve this. For this we have to create a ClassResolver. This will be instantiated and asked for the solution.

  @ResponsibleFor(Service.class)
  public static class ServiceClassResolver implements ClassResolver<Service> {
    @Override
    public Class<? extends Service> resolve(final Class<Service> interf) {
      return ServiceB.class;
    }
  }

Now the container is able to ask the ClassResolver, what will be the right implementation to use. In our case, the mock.

Here you can see, one of the jUnit Tests that we are using to test the ClassResolver. ClassResolverTest014.java

  @Before
  public void setUp() throws Exception {
    DI.clearReflectionModel();
    DI.activatePackages("org.rapidpm");
    DI.activatePackages(this.getClass());
  }

  public static Boolean toggle = true;

  @Test
  public void test001() throws Exception {
    Assert.assertEquals(ServiceB.class, DI.activateDI(Service.class).getClass());
    Assert.assertEquals(ServiceA.class, DI.activateDI(Service.class).getClass());
    Assert.assertEquals(ServiceB.class, DI.activateDI(Service.class).getClass());
    DI.clearReflectionModel();
  }

  public interface Service {
    String doWork(String txt);
  }

  public static class ServiceA implements Service {
    public String doWork(String txt) {
      return txt + "A";
    }
  }

  public static class ServiceB implements Service {
    public String doWork(String txt) {
      return txt + "B";
    }
  }

  @ResponsibleFor(Service.class)
  public static class ServiceClassResolver implements ClassResolver<Service> {
    @Override
    public Class<? extends Service> resolve(final Class<Service> interf) {
      toggle = !toggle;
      System.out.println("toggle = " + toggle);
      return (toggle) ? ServiceA.class : ServiceB.class;
    }
  }