6

I am running Wiremock on a servlet implementing this project from https://github.com/tomakehurst/wiremock/tree/master/sample-war

I am able to deploy this into a Tomcat and its working.

Now, I want to enable Response Templating on this server so that I can use handlebar templates to tweak the response body. I saw a few solutions related to Junit rules, directly setting this up from the code and also from standalone server but can't find a solution to enable response templating from a servlet.

How do I enable this from a wiremock servlet?

jacobcs
  • 539
  • 5
  • 14

3 Answers3

11

If you would like to use wiremock with docker, I have a sample docker-compose.yaml here with verbose logging and templating.

Spin up Wiremock in a docker container with docker-compose up.

docker-compose.yaml sample:

version: "3"
services:
 wiremock:
  image: rodolpheche/wiremock:latest
  ports:
    - "8181:8080"
  volumes:
    - ./__files/:/./home/wiremock/__files/
    - ./mappings/:/./home/wiremock/mappings/
  command:
    - -verbose
    - -global-response-templating

docker-compose up (in the directory you saved the yaml, and accept the requests for filesystem access) then you should be ready to go.

Wiremock url would be http://localhost:8181

After that do a recording with real data (http://localhost:8181/__admin/recorder)

Split the body to a separate file and place it in the __files folder. Point to the file with ""bodyFileName" in the request file (mappings)

I have some suggestions here. mobileera_wiremock_kb

Kb.
  • 7,240
  • 13
  • 56
  • 75
3

Okay finally i found the answer, You need to create your custom listner extending ServletContextListener and then programatically set the response templates.

public class CustomListener implements ServletContextListener {

private static final String APP_CONTEXT_KEY = "WireMockApp";

@Override
public void contextInitialized(ServletContextEvent sce) {
    ServletContext context = sce.getServletContext();

    boolean verboseLoggingEnabled = Boolean.parseBoolean(
            firstNonNull(context.getInitParameter("verboseLoggingEnabled"), "true"));
    WarConfiguration warConfiguration = new WarConfiguration(context);
    warConfiguration.extensionsOfType(MockTokenTemplate.class);
    final WireMockConfiguration wireMockConfiguration =WireMockConfiguration.wireMockConfig();
    wireMockConfiguration.extensions("com.test.MockTokenTemplate","com.test.MockTokenInqTemplate");
    //wireMockConfiguration.jettySettings();
    wireMockConfiguration.containerThreads(Integer.valueOf(200));
    wireMockConfiguration.disableRequestJournal()
            .containerThreads(Integer.valueOf(200))
            .jettyAcceptors(Integer.valueOf(-1))
            .jettyAcceptQueueSize(Integer.valueOf(1000))
            .jettyHeaderBufferSize(Integer.valueOf(8192));
    String fileSourceRoot = context.getInitParameter("WireMockFileSourceRoot");
 final FileSource fileSource = new ServletContextFileSource(context, fileSourceRoot);
    wireMockConfiguration.fileSource(fileSource);
    //wireMockConfiguration.usingFilesUnderDirectory("/WEB-INF/wiremock/");

    //wireMockConfiguration =(WireMockConfiguration) warConfiguration;
    WireMockApp wireMockApp = new WireMockApp(wireMockConfiguration, new NotImplementedContainer());
    context.setAttribute(APP_CONTEXT_KEY, wireMockApp);
    context.setAttribute(StubRequestHandler.class.getName(), wireMockApp.buildStubRequestHandler());
    context.setAttribute(AdminRequestHandler.class.getName(), wireMockApp.buildAdminRequestHandler());
    context.setAttribute(Notifier.KEY, new Slf4jNotifier(verboseLoggingEnabled));
}

/**
 * @param context Servlet context for parameter reading
 * @return Maximum number of entries or absent
 */
private Optional<Integer> readMaxRequestJournalEntries(ServletContext context) {
    String str = context.getInitParameter("maxRequestJournalEntries");
    if(str == null) {
        return Optional.absent();
    }
    return Optional.of(Integer.parseInt(str));
}

@Override
public void contextDestroyed(ServletContextEvent sce) {
}

}

Let me know if you need help in creating custom response templates.

user1697113
  • 683
  • 2
  • 14
  • 24
  • This was long back and I had to move on to different priorities, so couldn't test this out. Hope this helps anyone who is facing such a situation. – jacobcs May 13 '20 at 09:37
1

I handled adding definitionTransformer to ServletListener by extending and overriding the WireMockWebContextListener

This keeps the configuration stock as much as possible and uses Spring features to auto-register new Transformers without any other config change. Using latest wiremock artifact 2.26.3

Below is complete setup config and implementation.

public abstract class AbstractResponseDefinitionTransformer extends ResponseDefinitionTransformer implements Extension {

    @Override
    public String getName() {

    return WordUtils.uncapitalize(getClass().getSimpleName());
    }
}

@Component
public class CustomResponseDefinitionTransformer extends AbstractResponseDefinitionTransformer {

    @Override
    public ResponseDefinition transform(Request request, ResponseDefinition responseDefinition, FileSource files,
                                        Parameters parameters) {

        System.out.println("Hello World !!!");

        return responseDefinition;
    }
}

public class CustomWireMockWebContextListener extends WireMockWebContextListener {

    private static final String APP_CONTEXT_KEY = "WireMockApp";

    private final List<? extends AbstractResponseDefinitionTransformer> abstractResponseDefinitionTransformers;

    public CustomWireMockWebContextListener() {
        this(Collections.emptyList());
    }

    public CustomWireMockWebContextListener(
            List<? extends AbstractResponseDefinitionTransformer> abstractResponseDefinitionTransformers) {
        this.abstractResponseDefinitionTransformers = abstractResponseDefinitionTransformers;
    }

        @Override
        public void contextInitialized(ServletContextEvent sce) {

            super.contextInitialized(sce);

            final ServletContext context = sce.getServletContext();

            final WarConfiguration warConfiguration = buildCustomWarConfiguration(context);
            final WireMockApp wireMockApp = new WireMockApp(warConfiguration, new NotImplementedContainer());

            context.setAttribute(APP_CONTEXT_KEY, wireMockApp);
            context.setAttribute(StubRequestHandler.class.getName(), wireMockApp.buildStubRequestHandler());
            context.setAttribute(AdminRequestHandler.class.getName(), wireMockApp.buildAdminRequestHandler());
        }

        private WarConfiguration buildCustomWarConfiguration(final ServletContext context) {

            final Map<String, Extension> map = abstractResponseDefinitionTransformers.stream()
                    .collect(Collectors.toMap(AbstractResponseDefinitionTransformer::getName, transformer -> transformer));

            return new WarConfiguration(context) {
                @Override
                public <T extends Extension> Map<String, T> extensionsOfType(Class<T> extensionType) {

                    return (Map<String, T>) Maps.filterEntries(map, valueAssignableFrom(extensionType));
                }
            };
        }
}

@Configuration
public class WireMockConfiguration {

    @Autowired
    private List<? extends AbstractResponseDefinitionTransformer> abstractResponseDefinitionTransformers;

    @Bean
    public ServletListenerRegistrationBean wireMockWebContextListener() {
        final ServletListenerRegistrationBean bean = new ServletListenerRegistrationBean();
        bean.setEnabled(true);
        bean.setListener(new CustomWireMockWebContextListener(abstractResponseDefinitionTransformers));
        return bean;
    }
}
Ashish Thukral
  • 1,445
  • 1
  • 16
  • 26
  • this answer derives some inspiration from above answer by @user1697113 https://stackoverflow.com/a/54860279/2015965 – Ashish Thukral May 12 '20 at 11:02
  • 1
    As I mentioned in the above answer's comment, this was long ago. But hopefully it helps someone. Maybe me at a later time. Thanks – jacobcs May 13 '20 at 09:38