Using ArC outside Quarkus
Tags: quarkus, microservices, java, maven
Published: 2023-03-20 09:30:00

## What is ArC

ArC is build time oriented implementation of [CDI 2.0 - Contexts and Dependency Injection specification](https://jakarta.ee/specifications/cdi/2.0/). 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:

```java

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

@ApplicationScoped
public class ServiceImpl implements Service {

	@Inject
	Service2 service2;
	
	@Override
	public void serve() {

	}

}
```

### 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](https://maven.apache.org) 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:

```java
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
    }

}
```

### Bean processing

`BeanProcessor` need index for all classes that needed our application. So we use [Jandex](https://smallrye.io/jandex/jandex/3.0.5/index.html) for creating index of all classes. 

```java
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();
```

Then we can create `BeanProcessor`

```java
BeanProcessor.builder()
	.setApplicationIndex(index)
	.setComputingBeanArchiveIndex(index)
	.setImmutableBeanArchiveIndex(index)
	.setGenerateSources(true)
	.setOutput(new JarResourceOutput(generatedJarCreator))
	.setTransformUnproxyableClasses(true)
	.build();
```

`JarResourceOutput` writes generated by ArC classes and [service provider](https://docs.oracle.com/javase/tutorial/sound/SPI-intro.html) files into JAR

```java
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;
}
```

### Runtime

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

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

## Summary

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