Reputation: 483
I am generating the installer for both Windows and Linux systems. After the welcome screen, I have a CustomForm component where I take user details and then send them to a server using javax.ws.rs.client.ClientBuilder
. But in Windows, when the my Class tries to build the client from ClientBuilder, the installer throws java.lang.LinkageError: ClassCastException
. The whole log is stated below:
java.lang.LinkageError: ClassCastException: attempting to cast
jar:file:/C:/Users/lutful.kabir/AppData/Local/Temp/e4j363A.tmp_dir1460795758/user/javaee-api-7.0.jar!/javax/ws/rs/client/ClientBuilder.class to
jar:file:/C:/Users/lutful.kabir/AppData/Local/Temp/e4j363A.tmp_dir1460795758/user/javaee-api-7.0.jar!/javax/ws/rs/client/ClientBuilder.class
at javax.ws.rs.client.ClientBuilder.newBuilder(ClientBuilder.java:97)
at javax.ws.rs.client.ClientBuilder.newClient(ClientBuilder.java:114)
at install4j.AuthorizationHandler.verifyAuthorization(AuthorizationHandler.java:21)
at install4j.backendsetup.VerifyBackend.install(VerifyBackend.java:27)
at com.install4j.runtime.installer.InstallerContextImpl$2.fetchValue(InstallerContextImpl.java:167)
at com.install4j.runtime.installer.InstallerContextImpl$2.fetchValue(InstallerContextImpl.java:164)
at com.install4j.runtime.installer.helper.comm.actions.FetchObjectAction.execute(FetchObjectAction.java:14)
at com.install4j.runtime.installer.helper.comm.HelperCommunication.executeActionDirect(HelperCommunication.java:272)
at com.install4j.runtime.installer.helper.comm.HelperCommunication.executeActionInt(HelperCommunication.java:247)
at com.install4j.runtime.installer.helper.comm.HelperCommunication.executeActionChecked(HelperCommunication.java:185)
at com.install4j.runtime.installer.helper.comm.HelperCommunication.fetchObjectChecked(HelperCommunication.java:168)
at com.install4j.runtime.installer.InstallerContextImpl.performActionIntStatic(InstallerContextImpl.java:164)
at com.install4j.runtime.installer.InstallerContextImpl.performActionInt(InstallerContextImpl.java:152)
at com.install4j.runtime.installer.ContextImpl.performAction(ContextImpl.java:1099)
at com.install4j.runtime.installer.controller.Controller.executeAction(Controller.java:367)
at com.install4j.runtime.installer.controller.Controller.executeActions(Controller.java:333)
at com.install4j.runtime.installer.controller.Controller.handleCommand(Controller.java:194)
at com.install4j.runtime.installer.controller.Controller.start(Controller.java:94)
at com.install4j.runtime.installer.Installer.runInProcess(Installer.java:59)
at com.install4j.runtime.installer.Installer.main(Installer.java:46)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:606)
at com.exe4j.runtime.LauncherEngine.launch(LauncherEngine.java:62)
at com.exe4j.runtime.WinLauncher.main(WinLauncher.java:101)
at com.install4j.runtime.launcher.WinLauncher.main(WinLauncher.java:26)
The code for AuthorizationHandler
follows:
package install4j;
import java.net.ConnectException;
import javax.ws.rs.client.Client;
import javax.ws.rs.client.ClientBuilder;
import javax.ws.rs.client.Invocation;
import javax.ws.rs.client.Invocation.Builder;
import javax.ws.rs.client.WebTarget;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import com.install4j.api.Util;
import com.install4j.api.context.InstallerContext;
import installerconfigparams.utils.InstallerParameter;
public class AuthorizationHandler {
public static boolean verifyAuthorization(String authToken, InstallerContext context) throws ConnectException {
Client client = ClientBuilder.newClient();
WebTarget target = client.target(InstallerParameter.CENTRAL_SERVER_URL.getStringValue())
.path(InstallerParameter.PATH_BACKEND_VERIFICATION.getStringValue());
Builder builder = target.request(MediaType.APPLICATION_JSON);
builder.header(InstallerParameter.AUTHORIZATION_HEADER.getStringValue(), authToken);
Invocation invocation = builder.buildGet();
Response response;
response = invocation.invoke();
response.getStringHeaders();
int status = response.getStatus();
if (InstallerParameter.HTTP_200.getIntValue() != status) {
String args = response.getHeaderString("error");
Util.showErrorMessage(context.getMessage("installer.backend.login.invalid") + args);
return false;
}
Util.showMessage(context.getMessage("installer.backend.login.successful"));
return true;
}
Now, as far I know and based on my internet research, this can happen when there might be duplicate resources (from the log you can also see that the ClientBuilder
classes it is using are also from identical paths). I have made sure there are no duplicate jars added so that the installer can confuse it. I am not really well acquainted with ClassLoaders or with how it works for Install4j. I have also tried using the Run Script
action, by writing the codes directly there, but ended up having the same exception.
I have been using the same classes and methods since I have been building the Installer. And did not have any problem till today. I even checked out to my old Commit before I faced this problem. But the result is the same. And this problem only occurs for the installer in Windows.
Upvotes: 2
Views: 545
Reputation: 47965
JAX-WS uses the context class loader for some operations. Calling
Thread.currentThread().setContextClassLoader(getClass().getClassLoader());
sets the context class loader to the same class loader that loads the script, which is different from the system class loader since install4j 6.1.
Starting with install4j 6.1.2, the context class loader will be adjusted automatically so the above workaround will no longer be necessary.
Upvotes: 2