Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactor SPI interfaces, use io.avaje.jsonb.spi.JsonbExtension + other breaking changes #246

Merged
merged 15 commits into from
Jun 25, 2024
Merged
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -8,4 +8,5 @@ build/
*.project
*.class
.DS_Store
jsonb-generator/.factorypath
*.factorypath
jsonb-generator/io.avaje.jsonb.spi.JsonbExtension
5 changes: 3 additions & 2 deletions blackbox-test/src/main/java/module-info.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,6 @@
requires static io.avaje.jsonb;
requires java.validation;

provides io.avaje.jsonb.Jsonb.GeneratedComponent with org.example.jsonb.GeneratedJsonComponent;
}
provides io.avaje.jsonb.spi.JsonbExtension with org.example.customer.customtype.CustomTypeComponent, org.example.jsonb.GeneratedJsonComponent;

}
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@


import io.avaje.jsonb.*;
import io.avaje.jsonb.spi.JsonbComponent;

/**
* Register via service loading.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Objects;

final class ComponentReader {

Expand All @@ -24,14 +25,18 @@ final class ComponentReader {
}

void read() {
String componentFullName = loadMetaInfServices();
if (componentFullName != null) {
TypeElement moduleType = typeElement(componentFullName);
if (moduleType != null) {
componentMetaData.setFullName(componentFullName);
readMetaData(moduleType);
}
}
loadMetaInf().stream()
.map(APContext::typeElement)
.filter(Objects::nonNull)
.filter(t -> "io.avaje.jsonb.spi.GeneratedComponent".equals(t.getSuperclass().toString()))
.findFirst()
.ifPresent(
moduleType -> {
if (moduleType != null) {
componentMetaData.setFullName(moduleType.getQualifiedName().toString());
readMetaData(moduleType);
}
});
}

/**
Expand All @@ -56,11 +61,6 @@ private void readMetaData(TypeElement moduleType) {
}
}

private String loadMetaInfServices() {
final List<String> lines = loadMetaInf();
return lines.isEmpty() ? null : lines.get(0);
}

private List<String> loadMetaInf() {
try {
FileObject fileObject = processingEnv()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

final class Constants {

static final String META_INF_COMPONENT = "META-INF/services/io.avaje.jsonb.Jsonb$GeneratedComponent";
static final String META_INF_COMPONENT = "META-INF/services/io.avaje.jsonb.spi.JsonbExtension";
static final String JSONB_WILD = "io.avaje.jsonb.*";
static final String JSONB_SPI = "io.avaje.jsonb.spi.*";
static final String JSONB = "io.avaje.jsonb.Jsonb";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,7 @@ static void validateModule(String fqn) {

var buildPluginAvailable = buildPluginAvailable();
if (noProvides && !buildPluginAvailable) {
logError(module, "Missing `provides io.avaje.jsonb.Jsonb.GeneratedComponent with %s;`", fqn);
logError(module, "Missing `provides io.avaje.jsonb.spi.JsonbExtension with %s;`", fqn);
}

final var noDirectJsonb =
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,17 @@
import static io.avaje.jsonb.generator.ProcessingContext.createMetaInfWriterFor;
import static io.avaje.jsonb.generator.APContext.createSourceFile;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.Writer;
import java.util.List;
import java.util.Set;
import java.util.TreeSet;

import javax.tools.FileObject;
import javax.tools.JavaFileObject;
import javax.tools.StandardLocation;

final class SimpleComponentWriter {

Expand Down Expand Up @@ -48,14 +51,36 @@ void write() throws IOException {
}

void writeMetaInf() throws IOException {
var services = readExistingMetaInfServices();
final FileObject fileObject = createMetaInfWriterFor(Constants.META_INF_COMPONENT);
if (fileObject != null) {
services.add(metaData.fullName());
final Writer writer = fileObject.openWriter();
writer.write(metaData.fullName());
writer.write(String.join("\n", services));
writer.close();
}
}

private static Set<String> readExistingMetaInfServices() {
var services = new TreeSet<String>();
try (final var file =
APContext.filer()
.getResource(StandardLocation.CLASS_OUTPUT, "", Constants.META_INF_COMPONENT)
.toUri()
.toURL()
.openStream();
final var buffer = new BufferedReader(new InputStreamReader(file)); ) {

String line;
while ((line = buffer.readLine()) != null) {
line.replaceAll("\\s", "").replace(",", "\n").lines().forEach(services::add);
}
} catch (Exception e) {
// not a critical error
}
return services;
}

private void writeRegister() {
writer.append(" @Override").eol();
writer.append(" public void register(Jsonb.Builder builder) {").eol();
Expand Down Expand Up @@ -91,7 +116,7 @@ private void writeClassStart() {
writeMetaDataEntry(all);
writer.append("})").eol();

writer.append("public class %s implements Jsonb.GeneratedComponent {", shortName).eol().eol();
writer.append("public class %s implements GeneratedComponent {", shortName).eol().eol();
}

private void writeMetaDataEntry(List<String> entries) {
Expand Down
6 changes: 3 additions & 3 deletions jsonb-inject-plugin/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -18,15 +18,15 @@
<dependency>
<groupId>io.avaje</groupId>
<artifactId>avaje-jsonb</artifactId>
<version>1.10-RC1</version>
<version>1.11</version>
<scope>provided</scope>
<optional>true</optional>
</dependency>

<dependency>
<groupId>io.avaje</groupId>
<artifactId>avaje-inject</artifactId>
<version>9.12</version>
<version>10.0-RC7</version>
<scope>provided</scope>
<optional>true</optional>
</dependency>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,23 +1,26 @@
package io.avaje.jsonb.inject;

import java.lang.reflect.Type;

import io.avaje.inject.BeanScopeBuilder;
import io.avaje.inject.spi.InjectPlugin;
import io.avaje.jsonb.Jsonb;
import io.avaje.jsonb.stream.BufferRecycleStrategy;

/**
* Plugin for avaje inject that provides a default Jsonb instance.
*/
public final class DefaultJsonbProvider implements io.avaje.inject.spi.Plugin {
public final class DefaultJsonbProvider implements InjectPlugin {

@Override
public Class<?>[] provides() {
return new Class<?>[]{Jsonb.class};
public Type[] provides() {
return new Type[]{Jsonb.class};
}

@Override
public void apply(BeanScopeBuilder builder) {
builder.provideDefault(null, Jsonb.class, () -> {
var props = builder.propertyPlugin();
var props = builder.configPlugin();

return Jsonb.builder()
.failOnUnknown(props.equalTo("jsonb.deserialize.failOnUnknown", "true"))
Expand Down
2 changes: 1 addition & 1 deletion jsonb-inject-plugin/src/main/java/module-info.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,5 @@
requires transitive io.avaje.jsonb;
requires transitive io.avaje.inject;

provides io.avaje.inject.spi.Plugin with io.avaje.jsonb.inject.DefaultJsonbProvider;
provides io.avaje.inject.spi.InjectExtension with io.avaje.jsonb.inject.DefaultJsonbProvider;
}
7 changes: 7 additions & 0 deletions jsonb/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,13 @@
<version>4.0.10</version>
<scope>provided</scope>
<optional>true</optional>
</dependency>

<dependency>
<groupId>io.avaje</groupId>
<artifactId>avaje-spi-service</artifactId>
<version>${spi.version}</version>
<optional>true</optional>
</dependency>

<dependency>
Expand Down
20 changes: 1 addition & 19 deletions jsonb/src/main/java/io/avaje/jsonb/Jsonb.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@

import io.avaje.jsonb.core.DefaultBootstrap;
import io.avaje.jsonb.spi.AdapterFactory;
import io.avaje.jsonb.spi.Bootstrap;
import io.avaje.jsonb.spi.JsonStreamAdapter;
import io.avaje.jsonb.spi.JsonbComponent;
import io.avaje.jsonb.spi.PropertyNames;
import io.avaje.jsonb.stream.BufferRecycleStrategy;
import io.avaje.jsonb.stream.JsonOutput;
Expand All @@ -13,8 +13,6 @@
import java.io.Reader;
import java.io.Writer;
import java.lang.reflect.Type;
import java.util.Iterator;
import java.util.ServiceLoader;

/**
* Provides access to json adapters by type.
Expand Down Expand Up @@ -102,10 +100,6 @@ public interface Jsonb {
* }</pre>
*/
static Builder builder() {
Iterator<Bootstrap> bootstrapService = ServiceLoader.load(Bootstrap.class).iterator();
if (bootstrapService.hasNext()) {
return bootstrapService.next().builder();
}
return DefaultBootstrap.builder();
}

Expand Down Expand Up @@ -424,16 +418,4 @@ interface AdapterBuilder {
*/
JsonAdapter<?> build(Jsonb jsonb);
}

/**
* Components register JsonAdapters Jsonb.Builder
*/
@FunctionalInterface
interface GeneratedComponent extends JsonbComponent {

/**
* Register JsonAdapters with the Builder.
*/
void register(Builder builder);
}
}
17 changes: 0 additions & 17 deletions jsonb/src/main/java/io/avaje/jsonb/JsonbComponent.java

This file was deleted.

10 changes: 5 additions & 5 deletions jsonb/src/main/java/io/avaje/jsonb/core/DJsonb.java
Original file line number Diff line number Diff line change
Expand Up @@ -41,9 +41,9 @@ final class DJsonb implements Jsonb {
if (adapter != null) {
this.io = adapter;
} else {
Iterator<AdapterFactory> iterator = ServiceLoader.load(AdapterFactory.class).iterator();
if (iterator.hasNext()) {
this.io = iterator.next().create(serializeNulls, serializeEmpty, failOnUnknown);
var adapterFactoryOptional = ExtensionLoader.adapterFactory();
if (adapterFactoryOptional.isPresent()) {
this.io = adapterFactoryOptional.get().create(serializeNulls, serializeEmpty, failOnUnknown);
} else {
this.io = new JsonStream(serializeNulls, serializeEmpty, failOnUnknown, strategy);
}
Expand Down Expand Up @@ -290,10 +290,10 @@ public Builder add(JsonAdapter.Factory factory) {

private void registerComponents() {
// first register all user defined JsonbComponent
for (JsonbComponent next : ServiceLoader.load(JsonbComponent.class)) {
for (JsonbComponent next : ExtensionLoader.userComponents()) {
next.register(this);
}
for (GeneratedComponent next : ServiceLoader.load(GeneratedComponent.class)) {
for (GeneratedComponent next : ExtensionLoader.generatedComponents()) {
next.register(this);
}
}
Expand Down
43 changes: 43 additions & 0 deletions jsonb/src/main/java/io/avaje/jsonb/core/ExtensionLoader.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
package io.avaje.jsonb.core;

import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import java.util.ServiceLoader;

import io.avaje.jsonb.spi.AdapterFactory;
import io.avaje.jsonb.spi.GeneratedComponent;
import io.avaje.jsonb.spi.JsonbComponent;
import io.avaje.jsonb.spi.JsonbExtension;

/** Load all the services using the common service interface. */
final class ExtensionLoader {

private static final List<GeneratedComponent> generatedComponents = new ArrayList<>();
private static final List<JsonbComponent> userComponents = new ArrayList<>();
private static Optional<AdapterFactory> adapterFactory = Optional.empty();

static {
for (var spi : ServiceLoader.load(JsonbExtension.class)) {
if (spi instanceof GeneratedComponent) {
generatedComponents.add((GeneratedComponent) spi);
} else if (spi instanceof JsonbComponent) {
userComponents.add((JsonbComponent) spi);
} else if (spi instanceof AdapterFactory) {
adapterFactory = Optional.of((AdapterFactory) spi);
}
}
}

static List<GeneratedComponent> generatedComponents() {
return generatedComponents;
}

static List<JsonbComponent> userComponents() {
return userComponents;
}

static Optional<AdapterFactory> adapterFactory() {
return adapterFactory;
}
}
2 changes: 1 addition & 1 deletion jsonb/src/main/java/io/avaje/jsonb/spi/AdapterFactory.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
/**
* Factory that is service loaded to create the adapter for underlying json parsing and generation.
*/
public interface AdapterFactory {
public interface AdapterFactory extends JsonbExtension {

/**
* Create the adapter to use for the underlying json parsing and generation.
Expand Down
15 changes: 0 additions & 15 deletions jsonb/src/main/java/io/avaje/jsonb/spi/Bootstrap.java

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
package io.avaje.jsonb.spi;

/** Component interface registers generated JsonAdapters to the Jsonb.Builder */
@FunctionalInterface
public interface GeneratedComponent extends JsonbComponent, JsonbExtension {}
Loading
Loading