/******************************************************************************* * 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]; } }