[jboss-jira] [JBoss JIRA] (WFLY-3527) Improper noargs constructor assumption leads to NullPointerException
Randahl Fink Isaksen (JIRA)
issues at jboss.org
Mon Jun 23 11:43:27 EDT 2014
[ https://issues.jboss.org/browse/WFLY-3527?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=12978660#comment-12978660 ]
Randahl Fink Isaksen edited comment on WFLY-3527 at 6/23/14 11:42 AM:
----------------------------------------------------------------------
Hi David. Thank you very much for getting back to me. I am not sure what you mean by "serialized as a regular class", but what is happening is this:
1. I am receiving user input client side.
2. To validate this user input, I am sending an instance of EmailAddress and one of String to an EJB on WildFly, specifically this method:
public Validation validateVerificationCode(EmailAddress emailAddress, String code) {
3. The server responds by sending back an instance of a Validation, a class which I am appending below.
4. The error only occurs when I am returning Validation.INVALID, which is probably caused by the fact that I use readResolve to turn all instances of Validation.VALID into the same instance.
If you have any suggestions on how I can work around this bug until it is solved, I am all ears – I am on a deadline, and this bug is a killer.
public class Validation implements Identified<String>, Serializable {
private static final Settings DEFAULT_SETTINGS = Settings.create(
Validation.class,
new Setting<>("invalid", "Not correct", ENGLISH),
new Setting<>("invalid", "Ikke korrekt", DANISH),
new Setting<>("validating", "Validating...", ENGLISH),
new Setting<>("validating", "Undersøger...", DANISH)
);
public static final Validation VALID = new Validation();
public static final Validation VALIDATING = new Validation(DEFAULT_SETTINGS, "validating");
public static final Validation INVALID = new Validation(DEFAULT_SETTINGS, "invalid");
private Settings defaultSettings;
private String id;
private List<Parameter> parameters;
private Validity validity;
private Validation() {
this.validity = Validity.VALID;
}
public Validation(Settings defaultSettings, String id, Parameter... parameters) {
this(Validity.INVALID, defaultSettings, id, parameters);
}
public Validation(Validity validity, Settings defaultSettings, String id, Parameter... parameters) {
Guardian.notNull("validity", validity);
Guardian.notNull("settings", defaultSettings);
Guardian.notNull("id", id);
this.validity = validity;
this.defaultSettings = defaultSettings;
this.id = id;
this.parameters = Arrays.asList(parameters);
}
@Override
public String toString() {
if(this == VALID)
return "";
return defaultSettings.getString(id, (Parameter[]) parameters.toArray());
}
@Override
public String getId() {
return id;
}
public List<Parameter> getParameters() {
return parameters;
}
public Settings getDefaultSettings() {
return defaultSettings;
}
public Validity getValidity() {
return validity;
}
public boolean isValid() {
return validity == Validity.VALID;
}
private Object readResolve() throws ObjectStreamException {
if(isValid())
return VALID;
else return this;
}
}
was (Author: randahl):
Hi David. Thank you very much for getting back to me. I am not sure what you mean by "serialized as a regular class", but what is happening is this:
1. I am receiving user input client side.
2. To validate this user input, I am sending a String to an EJB on WildFly, specifically this method:
public Validation validateVerificationCode(EmailAddress emailAddress, String code) {
3. The server responds by sending back an instance of a Validation, a class which I am appending below.
4. The error only occurs when I am returning Validation.INVALID, which is probably caused by the fact that I use readResolve to turn all instances of Validation.VALID into the same instance.
If you have any suggestions on how I can work around this bug until it is solved, I am all ears – I am on a deadline, and this bug is a killer.
public class Validation implements Identified<String>, Serializable {
private static final Settings DEFAULT_SETTINGS = Settings.create(
Validation.class,
new Setting<>("invalid", "Not correct", ENGLISH),
new Setting<>("invalid", "Ikke korrekt", DANISH),
new Setting<>("validating", "Validating...", ENGLISH),
new Setting<>("validating", "Undersøger...", DANISH)
);
public static final Validation VALID = new Validation();
public static final Validation VALIDATING = new Validation(DEFAULT_SETTINGS, "validating");
public static final Validation INVALID = new Validation(DEFAULT_SETTINGS, "invalid");
private Settings defaultSettings;
private String id;
private List<Parameter> parameters;
private Validity validity;
private Validation() {
this.validity = Validity.VALID;
}
public Validation(Settings defaultSettings, String id, Parameter... parameters) {
this(Validity.INVALID, defaultSettings, id, parameters);
}
public Validation(Validity validity, Settings defaultSettings, String id, Parameter... parameters) {
Guardian.notNull("validity", validity);
Guardian.notNull("settings", defaultSettings);
Guardian.notNull("id", id);
this.validity = validity;
this.defaultSettings = defaultSettings;
this.id = id;
this.parameters = Arrays.asList(parameters);
}
@Override
public String toString() {
if(this == VALID)
return "";
return defaultSettings.getString(id, (Parameter[]) parameters.toArray());
}
@Override
public String getId() {
return id;
}
public List<Parameter> getParameters() {
return parameters;
}
public Settings getDefaultSettings() {
return defaultSettings;
}
public Validity getValidity() {
return validity;
}
public boolean isValid() {
return validity == Validity.VALID;
}
private Object readResolve() throws ObjectStreamException {
if(isValid())
return VALID;
else return this;
}
}
> Improper noargs constructor assumption leads to NullPointerException
> --------------------------------------------------------------------
>
> Key: WFLY-3527
> URL: https://issues.jboss.org/browse/WFLY-3527
> Project: WildFly
> Issue Type: Bug
> Security Level: Public(Everyone can see)
> Affects Versions: 8.0.0.Final
> Reporter: Randahl Fink Isaksen
> Assignee: David Lloyd
> Priority: Critical
>
> As shown in the stack trace below, I have received a NullPointerException from Wildfly. Looking at the Wildfly code, it seems to me that the class org.jboss.marshalling.reflect.SerializableClass improperly requires serializable classes to have a noargs constructor.
> The NullPointerException occurs in line 514:
> 514: return constructor.newInstance(args);
> so the reason for the NullPointerException is that the parameter constructor is null.
> Now, if you look at line 488, you see that the constructor parameter stems from the method invokation
> 488: return invokeConstructorNoException(nonInitConstructor);
> so the question is: When is nonInitConstructor defined, and why is it null?
> The answer can be found in line 160
> 160: nonInitConstructor = lookupNonInitConstructor(subject);
> and that method starts in line 550
> 550 private static <T> Constructor<T> More ...lookupNonInitConstructor(final
> …
> 555 topConstructor = current.getDeclaredConstructor();
> 556 } catch (NoSuchMethodException e) {
> 557 return null;
> 558 }
> …
> 563 }
> As you can see here, the method getDeclaredConstructor is invoked with no args, so Wildfly expects to find a noargs constructor. If non such constructor exists the NoSuchMethodException is thrown, caught, and null is returned.
> All in all I conclude, that creating a perfectly valid, serializable class with no noargs constructor makes Wildfly crash, and I believe this is a serious bug.
> CLASS WHICH MAKES WILDFLY FAIL
> public enum Validity {
> VALID(true),
> QUESTIONABLE(true),
> INVALID(false);
> private boolean valid;
>
> private Validity(boolean valid) {
> this.valid = valid;
> }
>
> public boolean isValid() {
> return valid;
> }
> }
> Note: Any enum is also Serializable
> STACK TRACE
> java.lang.reflect.InvocationTargetException
> at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
> at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
> at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
> at java.lang.reflect.Method.invoke(Method.java:483)
> at com.intuism.ui.validation.validator.ValidationTask.call(ValidationTask.java:49)
> at com.intuism.ui.validation.validator.ValidationTask.call(ValidationTask.java:23)
> at javafx.concurrent.Task$TaskCallable.call(Task.java:1426)
> at java.util.concurrent.FutureTask.run(FutureTask.java:266)
> at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
> at java.util.concurrent.FutureTask.run(FutureTask.java:266)
> at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
> at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
> at java.lang.Thread.run(Thread.java:744)
> Caused by: java.lang.NullPointerException
> at org.jboss.marshalling.reflect.SerializableClass.invokeConstructorNoException(SerializableClass.java:514)
> at org.jboss.marshalling.reflect.SerializableClass.callNonInitConstructor(SerializableClass.java:488)
> at org.jboss.marshalling.river.RiverUnmarshaller.doReadNewObject(RiverUnmarshaller.java:1270)
> at org.jboss.marshalling.river.RiverUnmarshaller.doReadObject(RiverUnmarshaller.java:276)
> at org.jboss.marshalling.river.RiverUnmarshaller.doReadObject(RiverUnmarshaller.java:213)
> at org.jboss.marshalling.river.RiverUnmarshaller.readFields(RiverUnmarshaller.java:1715)
> at org.jboss.marshalling.river.RiverUnmarshaller.doInitSerializable(RiverUnmarshaller.java:1631)
> at org.jboss.marshalling.river.RiverUnmarshaller.doReadNewObject(RiverUnmarshaller.java:1273)
> at org.jboss.marshalling.river.RiverUnmarshaller.doReadObject(RiverUnmarshaller.java:276)
> at org.jboss.marshalling.river.RiverUnmarshaller.doReadObject(RiverUnmarshaller.java:213)
> at org.jboss.marshalling.AbstractObjectInput.readObject(AbstractObjectInput.java:45)
> at org.jboss.ejb.client.remoting.MethodInvocationResponseHandler$MethodInvocationResultProducer.getResult(MethodInvocationResponseHandler.java:103)
> at org.jboss.ejb.client.EJBClientInvocationContext.getResult(EJBClientInvocationContext.java:272)
> at org.jboss.ejb.client.EJBObjectInterceptor.handleInvocationResult(EJBObjectInterceptor.java:64)
> at org.jboss.ejb.client.EJBClientInvocationContext.getResult(EJBClientInvocationContext.java:274)
> at org.jboss.ejb.client.EJBHomeInterceptor.handleInvocationResult(EJBHomeInterceptor.java:88)
> at org.jboss.ejb.client.EJBClientInvocationContext.getResult(EJBClientInvocationContext.java:274)
> at org.jboss.ejb.client.TransactionInterceptor.handleInvocationResult(TransactionInterceptor.java:46)
> at org.jboss.ejb.client.EJBClientInvocationContext.getResult(EJBClientInvocationContext.java:274)
> at org.jboss.ejb.client.ReceiverInterceptor.handleInvocationResult(ReceiverInterceptor.java:129)
> at org.jboss.ejb.client.EJBClientInvocationContext.getResult(EJBClientInvocationContext.java:262)
> at org.jboss.ejb.client.EJBClientInvocationContext.awaitResponse(EJBClientInvocationContext.java:437)
> at org.jboss.ejb.client.EJBInvocationHandler.doInvoke(EJBInvocationHandler.java:202)
> at org.jboss.ejb.client.EJBInvocationHandler.doInvoke(EJBInvocationHandler.java:181)
> at org.jboss.ejb.client.EJBInvocationHandler.invoke(EJBInvocationHandler.java:144)
> at com.sun.proxy.$Proxy4.validateVerificationCode(Unknown Source)
> ... 13 more
> Caused by: an exception which occurred:
> in object of type com.intuism.core.settings.EmbeddedSettings
> in field defaultSettings
> in object of type com.intuism.ui.validation.Validation
--
This message was sent by Atlassian JIRA
(v6.2.6#6264)
More information about the jboss-jira
mailing list