/*******************************************************************************
* Copyright 2019 Graz University of Technology
* MOA ZS has been developed in a cooperation between EGIZ
* and Graz University of Technology.
* Licensed under the EUPL, Version 1.2 or - as soon they will be approved by
* the European Commission - subsequent versions of the EUPL (the "Licence");
* You may not use this work except in compliance with the Licence.
* You may obtain a copy of the Licence at:
* https://joinup.ec.europa.eu/news/understanding-eupl-v12
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the Licence is distributed on an "AS IS" basis,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the Licence for the specific language governing permissions and
* limitations under the Licence.
*
* This product combines work with different licenses. See the "NOTICE" text
* file for details on the various modules and licenses.
* The "NOTICE" text file is part of the distribution. Any derivative works
* that you distribute must include a readable copy of the "NOTICE" text file.
*******************************************************************************/
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;
/**
* @author Christof Rabensteiner
*
*/
@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];
}
}