saw303
saw303

Reputation: 9072

Native Image: How to add custom file to the generated resource-config.json in Micronaut 3.7+

In my Micronaut application I use Google's LibPhoneNumber to parse and validate phone numbers. The library itself uses some ProtoBuf files that are part of the JAR such as

Is there a way to register these files somewhere in Micronaut (e.g. Gradle plugins, or annotation in source code) to append these custom resources to the generated resource-config.json that the Micronaut Gradle plugin produces?

I plan to register the ProtoBuf files using the following pattern.

{
  "resources": {
    "includes": [
      {
        "pattern": "\\Qcom/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_CH\\E"
      }
    ],
    "excludes": []
  },
  "bundles": []
}

Note: Micronaut generated resource pattern have been omitted in the listing above.

Upvotes: 2

Views: 497

Answers (1)

saw303
saw303

Reputation: 9072

One way how to do it, is to create a GraalVM feature that is automatically registered. I got inspired by the way Micronaut detects Flyway migrations and notices that with Resources#registerResource files can be registered for native-image.

import com.oracle.svm.core.annotate.AutomaticFeature;
import com.oracle.svm.core.jdk.Resources;
import java.util.List;
import org.graalvm.nativeimage.hosted.Feature;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * A GraalVM feature that includes LibPhoneNumber ProtoBuf files.
 *
 * <p>Forked from Micronaut Flyway:
 * https://github.com/micronaut-projects/micronaut-flyway/blob/master/flyway/src/main/java/io/micronaut/flyway/graalvm/FlywayFeature.java
 *
 * @author Silvio Wangler
 * @since 0.1.0
 */
@AutomaticFeature
final class GoogleLibPhoneNumberFeature implements Feature {

  private static final Logger LOG = LoggerFactory.getLogger(GoogleLibPhoneNumberFeature.class);

  @Override
  public void beforeAnalysis(BeforeAnalysisAccess access) {

    List<String> countries = List.of("CH", "IT", "DE", "FR", "GB", "AT", "LI");

    for (String country : countries) {
      try {
        String resourceName =
            "com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_" + country;
        String resourceName2 =
            "com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_" + country;
        Resources.registerResource(
            resourceName, access.getApplicationClassLoader().getResourceAsStream(resourceName));
        Resources.registerResource(
            resourceName2, access.getApplicationClassLoader().getResourceAsStream(resourceName2));
      } catch (Exception e) {
        LOG.error("Issue during processing Google LibPhoneNumber protobuf files", e);
      }
    }
  }
}

It is a limited implementation, since it does not include all countries supported by libphonenumber.

Upvotes: 1

Related Questions