package at.gv.egiz.moazs.util;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import java.util.function.Supplier;
import static at.gv.egiz.moazs.MoaZSException.moaZSException;
@Component
public class JAXBClassNotFoundFix {
private static final Logger log = LoggerFactory.getLogger(JAXBClassNotFoundFix.class);
private JAXBClassNotFoundFix() {}
/**
* Solves JAXB's "ClassNotFoundException: com.sun.xml.internal.bind.v2.ContextFactory" in Java >= 9
* by running func in a dedicated thread which has its context classloader replaced with a classloader that finds
* the ContextFactory.
*
* See https://sjhannah.com/blog/2018/11/21/jaxb-hell-on-jdk-9/
* Note: "runInTheadWithClassClassLoader" is not a typo.
* @param func function that is called in a dedicated thread.
* @param return value of func.
* @return
*/
public static A runInTheadWithClassClassLoader(Supplier func) {
final Object[] result = new Object[1];
final Exception[] error = new Exception[1];
Thread t = new Thread(() -> {
try {
result[0] = func.get();
} catch (Exception ex) {
error[0] = ex;
}
});
t.setContextClassLoader(JAXBClassNotFoundFix.class.getClassLoader());
t.start();
try {
t.join();
} catch (InterruptedException ex) {
log.error("Interrupted. ", ex);
throw moaZSException("Interrupted. ", ex);
}
if (error[0] != null) {
throw moaZSException("Could not run function.", error[0]);
}
return (A)result[0];
}
}