DEV Community

Efim Smykov
Efim Smykov

Posted on

Using ArC outside Quarkus

What is ArC

ArC is build time oriented implementation of CDI 2.0 - Contexts and Dependency Injection specification. ArC created by Quarkus team and used for DI in Quarkus. In this topic we will try use it not in Quarkus application.

How to use it

Bean definition

Because ArC based on CDI, for defining beans we will use standard annotations @ApplicationScoped for defining bean and @Inject for injecting beans into each other. It will look something like this:


import javax.inject.Inject;
import javax.enterprise.context.ApplicationScoped;

@ApplicationScoped
public class ServiceImpl implements Service {

    @Inject
    Service2 service2;

    @Override
    public void serve() {

    }

}
Enter fullscreen mode Exit fullscreen mode

Bean processing

Entry point for processing beans is BeanProcessor. It can be created via builder. And then we can use method process, which will resolve beans and generate resources for fast application startup.

Implementation

Maven plugin

We will be using ArC in Maven application. To modify build process we need to create plugin. We need to have access to application .class files and all compile and runtime dependencies. It looks something like this:

package com.nutrymaco.arc.maven.plugin;

import org.apache.maven.plugin.AbstractMojo;
import org.apache.maven.plugins.annotations.LifecyclePhase;
import org.apache.maven.plugins.annotations.Mojo;
import org.apache.maven.plugins.annotations.Parameter;
import org.apache.maven.plugins.annotations.ResolutionScope;
import org.apache.maven.project.MavenProject;

@Mojo(name = "build", defaultPhase = LifecyclePhase.PACKAGE, requiresDependencyResolution = ResolutionScope.COMPILE_PLUS_RUNTIME, threadSafe = true)
public class BuildMojo extends AbstractMojo {

    @Parameter(defaultValue = "${project}", readonly = true, required = true)
    private MavenProject project;

    @Override
    public void execute() {
            // build logic
    }

}
Enter fullscreen mode Exit fullscreen mode

Bean processing

BeanProcessor need index for all classes that needed our application. So we use Jandex for creating index of all classes.

Indexer indexer = new Indexer();

// add all .class files to index
indexJar(project.getArtifact().getFile(), indexer);

for (Artifact artifact : project.getArtifacts()) {
    indexJar(artifact.getFile(), indexer);
}

Index index = indexer.complete();
Enter fullscreen mode Exit fullscreen mode

Then we can create BeanProcessor

BeanProcessor.builder()
    .setApplicationIndex(index)
    .setComputingBeanArchiveIndex(index)
    .setImmutableBeanArchiveIndex(index)
    .setGenerateSources(true)
    .setOutput(new JarResourceOutput(generatedJarCreator))
    .setTransformUnproxyableClasses(true)
    .build();
Enter fullscreen mode Exit fullscreen mode

JarResourceOutput writes generated by ArC classes and service provider files into JAR

switch (resource.getType()) {
    case JAVA_CLASS:
        jar.addFile(
            target.resolve(resource.getName()) + ".class",
            resource.getData());
        break;
    case SERVICE_PROVIDER:
        jar.addFile(
            target.resolve("META-INF")
                  .resolve("services")
                  .resolve(resource.getName()).toString(),
            resource.getData());
        break;
    case JAVA_SOURCE:
        break;
}
Enter fullscreen mode Exit fullscreen mode

Runtime

In main class we should initialize container and then we can request for beans.

public class AppMain {
    public static void main(String[] args) {
        var container = Arc.initialize();
        var service = container.select(Service.class);
        service.serve();
    }
}
Enter fullscreen mode Exit fullscreen mode

Summary

As the result we add build time DI for our application. For that we created maven plugin in which we useBeanProcessor for processing bean definitions. Then in runtime we initialize container using Arc.initialize(). You can use it like this or use Quarkus to get more performance optimizations and features without extra actions like creating plugins.

Top comments (0)