Skip to content

Instantly share code, notes, and snippets.

@dalegaspi
Last active December 29, 2022 19:51
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save dalegaspi/d6ce6d179fa6887fc76293839fe93ac6 to your computer and use it in GitHub Desktop.
Save dalegaspi/d6ce6d179fa6887fc76293839fe93ac6 to your computer and use it in GitHub Desktop.
WireMock with Maven, Reflection, and Clojure
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.acme</groupId>
<artifactId>programmatic-services-mock</artifactId>
<version>1.0-SNAPSHOT</version>
<dependencies>
<dependency>
<groupId>com.github.tomakehurst</groupId>
<artifactId>wiremock-jre8</artifactId>
<version>2.35.0</version>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-engine</artifactId>
<version>5.9.0</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>1.4.5</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>2.0.5</version>
</dependency>
<dependency>
<groupId>org.clojure</groupId>
<artifactId>clojure</artifactId>
<version>1.11.1</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.24</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>io.vavr</groupId>
<artifactId>vavr</artifactId>
<version>0.10.4</version>
</dependency>
<dependency>
<groupId>org.clojure</groupId>
<artifactId>tools.logging</artifactId>
<version>1.2.4</version>
</dependency>
<dependency>
<groupId>clj-wiremock</groupId>
<artifactId>clj-wiremock</artifactId>
<version>0.3.0</version>
</dependency>
<dependency>
<groupId>cheshire</groupId>
<artifactId>cheshire</artifactId>
<version>5.11.0</version>
</dependency>
<dependency>
<groupId>clj-http</groupId>
<artifactId>clj-http</artifactId>
<version>3.12.3</version>
</dependency>
</dependencies>
<properties>
<maven.compiler.source>17</maven.compiler.source>
<maven.compiler.target>17</maven.compiler.target>
</properties>
<build>
<plugins>
<plugin>
<groupId>com.theoryinpractise</groupId>
<artifactId>clojure-maven-plugin</artifactId>
<version>1.8.3</version>
<extensions>true</extensions>
<executions>
<execution>
<id>compile</id>
<goals>
<goal>compile</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<version>1.6.0</version>
<executions>
<execution>
<id>start-wiremock</id>
<phase>pre-integration-test</phase>
<goals>
<goal>java</goal>
</goals>
<configuration>
<mainClass>com.github.tomakehurst.wiremock.standalone.WireMockServerRunner</mainClass>
<arguments>--verbose</arguments>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
<repositories>
<repository>
<id>clojars.org</id>
<url>https://clojars.org/repo</url>
</repository>
</repositories>
</project>
package com.acme;
import clojure.java.api.Clojure;
import clojure.lang.IFn;
import clojure.lang.ISeq;
import clojure.lang.SeqIterator;
import io.vavr.control.Either;
import io.vavr.control.Try;
import lombok.extern.slf4j.Slf4j;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.List;
/**
* @author Dexter Legaspi
*/
@Slf4j
public class WireMockConfigurations {
/**
* Java WireMockConfigurers
*
* @see WireMockConfigurer
* @param packageName the package
* @return Either error or the list of WireMockConfigurers
*/
@SuppressWarnings("unchecked")
public static List<Either<Throwable, WireMockConfigurer>> getJavaConfigurers(String packageName) {
// https://www.baeldung.com/java-find-all-classes-in-package#1-system-class-loader
var packagePath = packageName.replaceAll("[.]", "/");
var classLoader = ClassLoader.getSystemClassLoader();
var resources = Try.of(() -> classLoader.getResourceAsStream(packagePath))
.map(i -> new BufferedReader(new InputStreamReader(i)))
.map(b -> b.lines().filter(line -> line.endsWith(".class")).map(Try::success))
.get();
return resources.map(
s -> s.mapTry(c -> (Class<? extends WireMockConfigurer>) Class
.forName(packageName + "." + c.substring(0, c.lastIndexOf('.'))))
.mapTry(c -> (WireMockConfigurer) c.getDeclaredConstructor().newInstance())
.toEither())
.toList();
}
public static List<Either<Throwable, WireMockConfigurer>> getClojureConfigurers(String namespace) {
// Require the clojure.reflect library
IFn require = Clojure.var("clojure.core", "require");
require.invoke(Clojure.read("clojure.repl"));
// List the functions in the namespace
require.invoke(Clojure.read(namespace));
IFn dir = Clojure.var("clojure.repl", "dir-fn");
var functions = (ISeq) dir.invoke(Clojure.read(namespace));
var fnames = new ArrayList<String>();
for (var iter = new SeqIterator(functions); iter.hasNext();) {
fnames.add(iter.next().toString());
}
return fnames.stream()
// https://github.com/stuarthalloway/clojure-from-java
.map(fn -> Try.of(() -> (WireMockConfigurer) ((Clojure.var(namespace, fn)).call())))
.filter(Try::isSuccess).map(Try::toEither)
.toList();
}
public static final int WIREMOCK_PORT = Integer.parseInt(System.getProperty("PROGRAMMATIC_MOCK_PORT", "8080"));
public static String CONFIGURER_PACKAGE = "com.integralads.programmatic.mock.configurers";
public static void main(String[] args) {
getJavaConfigurers(CONFIGURER_PACKAGE)
.forEach(configurers -> configurers.forEach(c -> {
log.info("Running Java configurer {}", c.getClass().getSimpleName());
c.configure(WIREMOCK_PORT);
}));
getClojureConfigurers(CONFIGURER_PACKAGE)
.forEach(configurers -> configurers.forEach(c -> {
log.info("Running Clojure configurer {}", c.getClass().getSimpleName());
c.configure(WIREMOCK_PORT);
}));
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment