StevenPG
StevenPG

Reputation: 463

Hazelcast with Spring Boot 3 GraalVM Native NoSuchMethodError

Migrated a Spring Cloud Gateway project to Spring Boot 3.1.2 and the following native configuration

{
  "resources":{
    "includes":[
      {"pattern":"hazelcast.yaml"}
    ]}
}

Configured Hazelcast beans and they are found by GraalVM runtime search

public class CacheConfig__BeanDefinitions {

  public static BeanDefinition getCacheConfigBeanDefinition() {
    RootBeanDefinition beanDefinition = new RootBeanDefinition(CacheConfig.class);
    beanDefinition.setInstanceSupplier(CacheConfig::new);
    return beanDefinition;
  }

  private static BeanInstanceSupplier<HazelcastInstance> getHazelcastInstanceInstanceSupplier() {
    return BeanInstanceSupplier.<HazelcastInstance>forFactoryMethod(CacheConfig.class, "hazelcastInstance", Config.class)
            .withGenerator((registeredBean, args) -> registeredBean.getBeanFactory().getBean(CacheConfig.class).hazelcastInstance(args.get(0)));
  }

  public static BeanDefinition getHazelcastInstanceBeanDefinition() {
    RootBeanDefinition beanDefinition = new RootBeanDefinition();
    beanDefinition.setTargetType(HazelcastInstance.class);
    beanDefinition.setDestroyMethodNames("shutdown");
    beanDefinition.setInstanceSupplier(getHazelcastInstanceInstanceSupplier());
    return beanDefinition;
  }

  private static BeanInstanceSupplier<Config> getHazelCastConfigInstanceSupplier() {
    return BeanInstanceSupplier.<Config>forFactoryMethod(CacheConfig.class, "hazelCastConfig", String.class, CacheConfigurationProperties.class)
            .withGenerator((registeredBean, args) -> registeredBean.getBeanFactory().getBean(CacheConfig.class).hazelCastConfig(args.get(0), args.get(1)));
  }

  public static BeanDefinition getHazelCastConfigBeanDefinition() {
    RootBeanDefinition beanDefinition = new RootBeanDefinition();
    beanDefinition.setTargetType(Config.class);
    beanDefinition.setInstanceSupplier(getHazelCastConfigInstanceSupplier());
    return beanDefinition;
  }

Configuration class Hazelcast beans are configured in has @Configuration(proxyBeanMethods = false)

hazelcast.yaml

hazelcast:
  network:
    join:
      multicast:
        enabled: false

However, when running the application the following error occurs:

org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'org.springframework.boot.actuate.autoconfigure.metrics.cache.CacheMetricsRegistrarConfiguration': Instantiation of supplied bean failed
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.obtainFromSupplier(AbstractAutowireCapableBeanFactory.java:1220) ~[api-gateway:6.0.11]
Caused by: java.lang.ExceptionInInitializerError: null
        at io.micrometer.core.instrument.binder.cache.HazelcastCacheMetrics.<init>(HazelcastCacheMetrics.java:79) ~[api-gateway:1.11.2]
Caused by: java.lang.NoSuchMethodException: no such method: com.hazelcast.map.IMap.getName()String/invokeInterface
Caused by: java.lang.NoSuchMethodError: com.hazelcast.map.IMap.getName()

I can't figure out when debugging a GraalVM application what one is supposed to do when confronted with String/invokeInterface.

Attempted to resolve by:

  1. Included reachability-metadata which includes Hazelcast 5.2.1 runtime hints
  2. https://docs.hazelcast.org/docs/5.1/javadoc/com/hazelcast/map/IMap.html
  3. Added
{
        "condition": {
          "typeReachable": "io.micrometer.core.instrument.binder.cache.HazelcastCacheMetrics"
        },
        "name": " com.hazelcast.map.IMap",
        "methods": [
          {
            "name": "getName",
            "parameterTypes": []
          }
        ]
      }

From what I understand from the error, the issue stems from Spring Boot Actuator attempting to access Hazelcast cache statistics/metrics and being unable to find the IMap method.

I'm not sure how I can hint the runtime to be aware of this at build-time.

Upvotes: 0

Views: 511

Answers (1)

blagh
blagh

Reputation: 11

Also ran into this issue, sadly. As far as I can tell, it is a bug on Micrometer side, so reported there: https://github.com/micrometer-metrics/micrometer/issues/5604

Upvotes: 1

Related Questions