Hi, I'm trying to get WireMock (standalone) workin...
# help
r
Hi, I'm trying to get WireMock (standalone) working with native compilation. The setup is Spring Boot 3 with Tomcat, WireMock Standalon 3.5.3. WireMock version used is standalone since WireMock requires Jetty 11 and Spring Boot uses Jetty 12 (and the standalone version uses "shaded" dependencies). However the native compilation fails. There are no native hints for WireMock nor the bundled Jetty. Are there plans to support this? Have other people got this working? Is work for Jetty 12 under way (which, I assume, will support native compilation)?
l
Hi, there is already a release with jetty 12 support - https://www.wiremock.io/post/wiremock-3-5-2-released This example here shows how to use this with spring boot - https://github.com/wiremock/wiremock-examples/tree/main/spring-boot/spring-boot-3/wiremock-jetty-12
r
Ok, I'll try that... thanks
👍 1
out of the box this still gives errors, are there examples where native compilation is used? (For instance PathSpecSet needs to be added for reflection)
l
To be honest I don't think we have looked into the native compilation side of things too much at this point.
r
alright, I'll carry on then... Now it is "read, fiddle a bit (register type, remove library, ... etc), recompile (wait 10+ minutes), try native executable, read exception, go to step 1" 😉
l
Ha, sounds like fun. Any help you can give in this area will be greatly appreciated
r
Hey Lee, I've got something working. I had to adjust a few things, I tried to remove the jetty 11 libraries from the WireMock. (Just removed one for now....) `build.gradle.kts`:
Copy code
val jettyVersion = "12.0.7"
    val wiremockVersion = "3.5.3"

    implementation("org.wiremock:wiremock-jetty12:${wiremockVersion}")
    implementation("org.eclipse.jetty.http2:jetty-http2-server:${jettyVersion}")    
    implementation("org.wiremock:wiremock:${wiremockVersion}") {
        // excluded because this seems to require more native compilation hints
        exclude("org.eclipse.jetty.http2")
    }
Further, where we start-up a WireMock server:
Copy code
WireMockServer wireMockServer = new WireMockServer(
        wireMockConfig()
        ...
        );
        
added:
            .templatingEnabled(false)
            
removed:
            .usingFilesUnderClasspath(WIREMOCK_BASE_DIRECTORY)
Both are to make sure I don't have to add more compilation hints.
...and... there are a "few" native compilation hints:
Copy code
**
 * Configuration that holds the WireMock native compilation hints.
 */
@Configuration
@ImportRuntimeHints(WireMockNativeCompilationHints.RuntimeHintsRegistrar.class)
@SuppressWarnings("PrivateConstructorForUtilityClass")
public class WireMockNativeCompilationHints {

  /**
   * The runtime-hints registrar.
   */
  static class RuntimeHintsRegistrar implements org.springframework.aot.hint.RuntimeHintsRegistrar {

    @Override
    public void registerHints(RuntimeHints hints,
        ClassLoader classLoader) {
      hints.reflection()
          .registerType(HashSet.class, // wiremock / jetty
              INVOKE_PUBLIC_CONSTRUCTORS,
              INVOKE_PUBLIC_METHODS)
          .registerType(PathSpecSet.class, // wiremock / jetty
              INVOKE_PUBLIC_CONSTRUCTORS,
              INVOKE_PUBLIC_METHODS)
          .registerType(AsciiLowerCaseSet.class, // wiremock / jetty
              INVOKE_PUBLIC_CONSTRUCTORS,
              INVOKE_PUBLIC_METHODS)

          .registerType(org.eclipse.jetty.ee10.servlets.CrossOriginFilter.class, // wiremock / jetty
              INVOKE_PUBLIC_CONSTRUCTORS,
              INVOKE_PUBLIC_METHODS)

          .registerType(CrossOriginFilter.class, // wiremock / jetty
              INVOKE_PUBLIC_CONSTRUCTORS,
              INVOKE_PUBLIC_METHODS)
          .registerType(ContentTypeSettingFilter.class, // wiremock / jetty
              INVOKE_PUBLIC_CONSTRUCTORS,
              INVOKE_PUBLIC_METHODS)
          .registerType(TrailingSlashFilter.class, // wiremock / jetty
              INVOKE_PUBLIC_CONSTRUCTORS,
              INVOKE_PUBLIC_METHODS)
          .registerType(WireMockHandlerDispatchingServlet.class, // wiremock / jetty
              INVOKE_PUBLIC_CONSTRUCTORS,
              INVOKE_PUBLIC_METHODS)

          .registerType(StringValuePattern.class, // wiremock
              INVOKE_DECLARED_CONSTRUCTORS,
              INTROSPECT_DECLARED_CONSTRUCTORS)

          .registerType(AbsentPattern.class, // wiremock
              INVOKE_DECLARED_CONSTRUCTORS,
              INTROSPECT_DECLARED_CONSTRUCTORS)
          .registerType(AbstractDateTimePattern.class, // wiremock
              INVOKE_DECLARED_CONSTRUCTORS,
              INTROSPECT_DECLARED_CONSTRUCTORS)
          .registerType(AbstractLogicalMatcher.class, // wiremock
              INVOKE_DECLARED_CONSTRUCTORS,
              INTROSPECT_DECLARED_CONSTRUCTORS)
          .registerType(AbstractRegexPattern.class, // wiremock
              INVOKE_DECLARED_CONSTRUCTORS,
              INTROSPECT_DECLARED_CONSTRUCTORS)
          .registerType(AbstractDateTimePattern.class, // wiremock
              INVOKE_DECLARED_CONSTRUCTORS,
              INTROSPECT_DECLARED_CONSTRUCTORS)
          .registerType(AnythingPattern.class, // wiremock
              INVOKE_DECLARED_CONSTRUCTORS,
              INTROSPECT_DECLARED_CONSTRUCTORS)
          .registerType(BeforeDateTimePattern.class, // wiremock
              INVOKE_DECLARED_CONSTRUCTORS,
              INTROSPECT_DECLARED_CONSTRUCTORS)
          .registerType(ContainsPattern.class, // wiremock
              INVOKE_DECLARED_CONSTRUCTORS,
              INTROSPECT_DECLARED_CONSTRUCTORS)
          .registerType(EqualToDateTimePattern.class, // wiremock
              INVOKE_DECLARED_CONSTRUCTORS,
              INTROSPECT_DECLARED_CONSTRUCTORS)
          .registerType(EqualToJsonPattern.class, // wiremock
              INVOKE_DECLARED_CONSTRUCTORS,
              INTROSPECT_DECLARED_CONSTRUCTORS)
          .registerType(EqualToPattern.class, // wiremock
              INVOKE_DECLARED_CONSTRUCTORS,
              INTROSPECT_DECLARED_CONSTRUCTORS)
          .registerType(EqualToXmlPattern.class, // wiremock
              INVOKE_DECLARED_CONSTRUCTORS,
              INTROSPECT_DECLARED_CONSTRUCTORS)
          .registerType(LogicalAnd.class, // wiremock
              INVOKE_DECLARED_CONSTRUCTORS,
              INTROSPECT_DECLARED_CONSTRUCTORS)
          .registerType(LogicalOr.class, // wiremock
              INVOKE_DECLARED_CONSTRUCTORS,
              INTROSPECT_DECLARED_CONSTRUCTORS)
          .registerType(MatchesJsonPathPattern.class, // wiremock
              INVOKE_DECLARED_CONSTRUCTORS,
              INTROSPECT_DECLARED_CONSTRUCTORS)
          .registerType(MatchesJsonSchemaPattern.class, // wiremock
              INVOKE_DECLARED_CONSTRUCTORS,
              INTROSPECT_DECLARED_CONSTRUCTORS)
          .registerType(MatchesXPathPattern.class, // wiremock
              INVOKE_DECLARED_CONSTRUCTORS,
              INTROSPECT_DECLARED_CONSTRUCTORS)
          .registerType(NegativeContainsPattern.class, // wiremock
              INVOKE_DECLARED_CONSTRUCTORS,
              INTROSPECT_DECLARED_CONSTRUCTORS)
          .registerType(NegativeRegexPattern.class, // wiremock
              INVOKE_DECLARED_CONSTRUCTORS,
              INTROSPECT_DECLARED_CONSTRUCTORS)
          .registerType(NotPattern.class, // wiremock
              INVOKE_DECLARED_CONSTRUCTORS,
              INTROSPECT_DECLARED_CONSTRUCTORS)
          .registerType(PathPattern.class, // wiremock
              INVOKE_DECLARED_CONSTRUCTORS,
              INTROSPECT_DECLARED_CONSTRUCTORS)
          .registerType(PathTemplatePattern.class, // wiremock
              INVOKE_DECLARED_CONSTRUCTORS,
              INTROSPECT_DECLARED_CONSTRUCTORS)
          .registerType(RegexPattern.class, // wiremock
              INVOKE_DECLARED_CONSTRUCTORS,
              INTROSPECT_DECLARED_CONSTRUCTORS)

          .registerType(Byte.class, // wiremock / jetty
              INVOKE_PUBLIC_METHODS)

          .registerType(HTTP2ServerConnection.class, INVOKE_PUBLIC_METHODS) // wiremock / jetty
      ;

      try {
        String valueOf = "valueOf";
        hints.reflection()
            .registerMethod(Boolean.class.getDeclaredMethod(valueOf, String.class),
                INVOKE) // wiremock / jetty
            .registerMethod(Byte.class.getDeclaredMethod(valueOf, String.class),
                INVOKE) // wiremock / jetty
            .registerMethod(Double.class.getDeclaredMethod(valueOf, String.class),
                INVOKE) // wiremock / jetty
            .registerMethod(Float.class.getDeclaredMethod(valueOf, String.class),
                INVOKE) // wiremock / jetty
            .registerMethod(Integer.class.getDeclaredMethod(valueOf, String.class),
                INVOKE) // wiremock / jetty
            .registerMethod(Long.class.getDeclaredMethod(valueOf, String.class),
                INVOKE) // wiremock / jetty
            .registerMethod(Short.class.getDeclaredMethod(valueOf, String.class),
                INVOKE) // wiremock / jetty
        ;
      } catch (NoSuchMethodException e) {
        throw new HawaiiException(e);
      }

      hints.resources()
          .registerPattern("assets/*") // wiremock
          .registerPattern("doc-index.html") // wiremock
          .registerPattern("helpers.nashorn.js") // wiremock
          .registerResourceBundle("jsv-messages") // wiremock
          .registerPattern("leap-second-dates.csv") // wiremock
          .registerPattern("keystore") // wiremock
          .registerPattern("version.properties") // wiremock
          .registerPattern("wiremock/jakarta/servlet/LocalStrings*") // wiremock
      ;

    }
  }
}
(sorry for the spam) Perhaps not all resources are required, but our app now runs with native compilation, with a bundled WireMock...