
| Key: |
ENHANCER-96
|
| Type: |
Bug
|
| Status: |
Resolved
|
| Resolution: |
Won't Fix
|
| Priority: |
Minor
|
| Assignee: |
Unassigned
|
| Reporter: |
Chris Beams
|
| Votes: |
0
|
| Watchers: |
0
|
|
If you were logged in you would be able to see more operations.
|
|
|
JPOX Enhancer
Created: 14/Jul/07 02:01 AM
Updated: 15/Jul/08 08:20 AM
|
|
| Component/s: |
None
|
| Affects Version/s: |
1.2.0-beta-3
|
| Fix Version/s: |
None
|
|
|
File Attachments:
|
1.
Person.java (0.5 kb)
2.
Person.java.enhanced (8 kb)
|
|
Environment:
|
java version "1.5.0_07"
Java(TM) 2 Runtime Environment, Standard Edition (build 1.5.0_07-164)
Java HotSpot(TM) Client VM (build 1.5.0_07-87, mixed mode, sharing)
Mac OS X 10.4.9
java version "1.5.0_07"
Java(TM) 2 Runtime Environment, Standard Edition (build 1.5.0_07-164)
Java HotSpot(TM) Client VM (build 1.5.0_07-87, mixed mode, sharing)
Mac OS X 10.4.9
|
|
|
In classes that define one or more constructors, but do NOT explicitly define a no-arg constructor, transient fields that have a default value do not get populated by JPOX upon object reconstitution.
I've attached both the original and enhanced (decompiled) versions of Person.java
In the original, you can see there is just one constructor that takes reads as follows:
package example;
import javax.jdo.annotations.*;
@PersistenceCapable
public class Person {
@Field
private final String name;
@Transient
private String currentLocation = "nowhere";
public Person(String name) {
this.name = name;
}
public String getName() {
return name;
}
public String getCurrentLocation() {
return currentLocation;
}
public void setCurrentLocation(String currentLocation) {
this.currentLocation = currentLocation;
}
}
After enhancement, two constructors are present in the class:
package decompiled;
import javax.jdo.PersistenceManager;
import javax.jdo.spi.*;
public class Person implements PersistenceCapable {
private final String name;
private String currentLocation;
public Person() {}
public Person(String s) {
currentLocation = "nowhere";
name = s;
}
// [...]
}
EXPECTED BEHAVIOR: The no-arg constructor should initialize currentLocation = "nowhere" just as the String constructor does.
ACTUAL BEHAVIOR: The transient field is not initialized, resulting in a null value (and thus, NullPointerExceptions) to clients of the class.
Also note that if I remove the String constructor from the original Person class, the enhanced version's no-arg constructor DOES properly initialize the transient field. Also, if I explicitly add an empty no-arg constructor to the original Person class, again enhancement works as expected, initializing the transient field. It's only in the case that Person defines one or more non-no-arg constructors that this problem arises.
Additionally, I tried marking this field as transient in the following several ways. None of them had any effect; the bug still manifested in each case.
@Transient
private String currentLocation = "nowhere";
private transient String currentLocation = "nowhere";
@Field(persistenceModifier = NONE)
private String currentLocation = "nowhere"
WORKAROUND:
The workaround for this bug is to explicitly declare a no-arg constructor in any classes that are affected (i.e.: classes that define one or more non-no-arg constructors AND do not define a no-arg constructor AND define transient fields with default values)
|
|
Description
|
In classes that define one or more constructors, but do NOT explicitly define a no-arg constructor, transient fields that have a default value do not get populated by JPOX upon object reconstitution.
I've attached both the original and enhanced (decompiled) versions of Person.java
In the original, you can see there is just one constructor that takes reads as follows:
package example;
import javax.jdo.annotations.*;
@PersistenceCapable
public class Person {
@Field
private final String name;
@Transient
private String currentLocation = "nowhere";
public Person(String name) {
this.name = name;
}
public String getName() {
return name;
}
public String getCurrentLocation() {
return currentLocation;
}
public void setCurrentLocation(String currentLocation) {
this.currentLocation = currentLocation;
}
}
After enhancement, two constructors are present in the class:
package decompiled;
import javax.jdo.PersistenceManager;
import javax.jdo.spi.*;
public class Person implements PersistenceCapable {
private final String name;
private String currentLocation;
public Person() {}
public Person(String s) {
currentLocation = "nowhere";
name = s;
}
// [...]
}
EXPECTED BEHAVIOR: The no-arg constructor should initialize currentLocation = "nowhere" just as the String constructor does.
ACTUAL BEHAVIOR: The transient field is not initialized, resulting in a null value (and thus, NullPointerExceptions) to clients of the class.
Also note that if I remove the String constructor from the original Person class, the enhanced version's no-arg constructor DOES properly initialize the transient field. Also, if I explicitly add an empty no-arg constructor to the original Person class, again enhancement works as expected, initializing the transient field. It's only in the case that Person defines one or more non-no-arg constructors that this problem arises.
Additionally, I tried marking this field as transient in the following several ways. None of them had any effect; the bug still manifested in each case.
@Transient
private String currentLocation = "nowhere";
private transient String currentLocation = "nowhere";
@Field(persistenceModifier = NONE)
private String currentLocation = "nowhere"
WORKAROUND:
The workaround for this bug is to explicitly declare a no-arg constructor in any classes that are affected (i.e.: classes that define one or more non-no-arg constructors AND do not define a no-arg constructor AND define transient fields with default values) |
Show » |
|