-
1. Re: Jboss Remoting (7.1.0.Final ) and java transient fields.
suikast42 Mar 2, 2012 6:02 AM (in response to suikast42)Hi it's me again,
I try my test with normal object serialasation of java. That works as well. I think the problem is in Jboss remoting.
Testcase with object serialisation:
@Test
public void testSerialisation(){
Employee emp = new Employee();
emp.setName("EmplName");
Assert.assertEquals("DEFAULT", emp.getTestString());
emp.setTestString("TestNew");
Assert.assertEquals("TestNew", emp.getTestString());
OutputStream fos = null;
String filename = "test";
try
{
fos = new FileOutputStream(filename);
ObjectOutputStream o = new ObjectOutputStream(fos);
o.writeObject(emp);
} catch (IOException e) {
System.err.println(e);
} finally {
try {
fos.close();
} catch (Exception e) {
e.printStackTrace();
}
}
InputStream fis = null;
BusinessObject empNew=null;
try
{
fis = new FileInputStream(filename);
ObjectInputStream o = new ObjectInputStream(fis);
empNew = (BusinessObject)o.readObject();
} catch (IOException e) {
System.err.println(e);
} catch (ClassNotFoundException e) {
System.err.println(e);
} finally {
try {
fis.close();
} catch (Exception e) {
}
}
Assert.assertNull(empNew.getTestString());
}
-
2. Re: Jboss Remoting (7.1.0.Final ) and java transient fields.
ctomc Mar 2, 2012 10:19 AM (in response to suikast42)Hi,
looks like it is a bug as you found out.
Can you please file an issue in jira, so it can attention from developers
--
tomaz
-
3. Re: Jboss Remoting (7.1.0.Final ) and java transient fields.
suikast42 Mar 3, 2012 5:21 AM (in response to ctomc)So if you can tell me how can I do this then I'll do it .
-
4. Re: Jboss Remoting (7.1.0.Final ) and java transient fields.
suikast42 Mar 3, 2012 5:30 AM (in response to ctomc)Ok. I done it.
-
5. Re: Jboss Remoting (7.1.0.Final ) and java transient fields.
suikast42 Mar 4, 2012 8:04 AM (in response to suikast42)I found a "clean" workarround for this problem.
Fortunately I have a toplevel entitty for my businessmodell. So I can do a little hack for the serialisation.
For setting the transient field to null due de deserialisation I do the thing shown below:
// Called by the serialisation mechanisim.
private void readObject( ObjectInputStream ois ) throws IOException
{
try
{
ois.defaultReadObject(); // Do your stuff like you want
setTransientFieldsToNull(getClass()); // Set all the transient fields to null
}
catch ( ClassNotFoundException e )
{
throw new IOException( e );
}
}
private void setTransientFieldsToNull(Class<?> clazz){
if(clazz.equals(Object.class)){
return;
}
for(Field field: clazz.getDeclaredFields()){
if(Modifier.isTransient(field.getModifiers())){
try {
field.setAccessible(true);
field.set(this, null);
} catch (Exception e) {
e.printStackTrace();
}
}
}
setTransientFieldsToNull(clazz.getSuperclass());
}
-
6. Re: Jboss Remoting (7.1.0.Final ) and java transient fields.
smarlow Mar 5, 2012 8:33 PM (in response to suikast42)Could you dig in a little deeper to see if this is a JPA or remoting issue. Would it be possible to eliminate JPA from the test?
I'm not sure how much this would help but maybe the below code change might also show more information:
private transient String test = getDefaultTestValue(); private String getDefaultTestValue() { Thread.dumpStack(); return "TEST"; }
That should show the call stack showing the 'test' field getting initialized.
-
7. Re: Jboss Remoting (7.1.0.Final ) and java transient fields.
suikast42 Mar 6, 2012 4:09 AM (in response to smarlow)Hi Scott,
this is the Dump with JPA:
10:03:22,414 ERROR [stderr] (MSC service thread 1-5) java.lang.Exception: Stack trace
10:03:22,414 ERROR [stderr] (MSC service thread 1-5) at java.lang.Thread.dumpStack(Thread.java:1249)
10:03:22,429 ERROR [stderr] (MSC service thread 1-5) at com.siemag.model.Employee.getDefaultTestValue(Employee.java:65)
10:03:22,429 ERROR [stderr] (MSC service thread 1-5) at com.siemag.model.Employee.<init>(Employee.java:25)
10:03:22,429 ERROR [stderr] (MSC service thread 1-5) at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
10:03:22,429 ERROR [stderr] (MSC service thread 1-5) at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:39)
10:03:22,429 ERROR [stderr] (MSC service thread 1-5) at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:27)
10:03:22,429 ERROR [stderr] (MSC service thread 1-5) at java.lang.reflect.Constructor.newInstance(Constructor.java:513)
10:03:22,429 ERROR [stderr] (MSC service thread 1-5) at org.hibernate.engine.internal.UnsavedValueFactory.instantiate(UnsavedValueFactory.java:46)
10:03:22,429 ERROR [stderr] (MSC service thread 1-5) at org.hibernate.engine.internal.UnsavedValueFactory.getUnsavedIdentifierValue(UnsavedValueFactory.java:68)
10:03:22,429 ERROR [stderr] (MSC service thread 1-5) at org.hibernate.tuple.PropertyFactory.buildIdentifierProperty(PropertyFactory.java:75)
10:03:22,445 ERROR [stderr] (MSC service thread 1-5) at org.hibernate.tuple.entity.EntityMetamodel.<init>(EntityMetamodel.java:143)
10:03:22,445 ERROR [stderr] (MSC service thread 1-5) at org.hibernate.persister.entity.AbstractEntityPersister.<init>(AbstractEntityPersister.java:498)
10:03:22,445 ERROR [stderr] (MSC service thread 1-5) at org.hibernate.persister.entity.SingleTableEntityPersister.<init>(SingleTableEntityPersister.java:142)
10:03:22,445 ERROR [stderr] (MSC service thread 1-5) at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
10:03:22,445 ERROR [stderr] (MSC service thread 1-5) at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:39)
10:03:22,445 ERROR [stderr] (MSC service thread 1-5) at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:27)
10:03:22,445 ERROR [stderr] (MSC service thread 1-5) at java.lang.reflect.Constructor.newInstance(Constructor.java:513)
10:03:22,461 ERROR [stderr] (MSC service thread 1-5) at org.hibernate.persister.internal.PersisterFactoryImpl.create(PersisterFactoryImpl.java:158)
10:03:22,461 ERROR [stderr] (MSC service thread 1-5) at org.hibernate.persister.internal.PersisterFactoryImpl.createEntityPersister(PersisterFactoryImpl.java:131)
10:03:22,461 ERROR [stderr] (MSC service thread 1-5) at org.hibernate.internal.SessionFactoryImpl.<init>(SessionFactoryImpl.java:345)
10:03:22,461 ERROR [stderr] (MSC service thread 1-5) at org.hibernate.cfg.Configuration.buildSessionFactory(Configuration.java:1737)
10:03:22,461 ERROR [stderr] (MSC service thread 1-5) at org.hibernate.ejb.EntityManagerFactoryImpl.<init>(EntityManagerFactoryImpl.java:84)
10:03:22,461 ERROR [stderr] (MSC service thread 1-5) at org.hibernate.ejb.Ejb3Configuration.buildEntityManagerFactory(Ejb3Configuration.java:904)
10:03:22,461 ERROR [stderr] (MSC service thread 1-5) at org.hibernate.ejb.Ejb3Configuration.buildEntityManagerFactory(Ejb3Configuration.java:889)
10:03:22,461 ERROR [stderr] (MSC service thread 1-5) at org.hibernate.ejb.HibernatePersistence.createContainerEntityManagerFactory(HibernatePersistence.java:73)
10:03:22,476 ERROR [stderr] (MSC service thread 1-5) at org.jboss.as.jpa.service.PersistenceUnitServiceImpl.createContainerEntityManagerFactory(PersistenceUnitServiceImpl.java:162)
10:03:22,476 ERROR [stderr] (MSC service thread 1-5) at org.jboss.as.jpa.service.PersistenceUnitServiceImpl.start(PersistenceUnitServiceImpl.java:85)
10:03:22,476 ERROR [stderr] (MSC service thread 1-5) at org.jboss.msc.service.ServiceControllerImpl$StartTask.startService(ServiceControllerImpl.java:1811)
10:03:22,476 ERROR [stderr] (MSC service thread 1-5) at org.jboss.msc.service.ServiceControllerImpl$StartTask.run(ServiceControllerImpl.java:1746)
10:03:22,476 ERROR [stderr] (MSC service thread 1-5) at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:886)
10:03:22,476 ERROR [stderr] (MSC service thread 1-5) at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:908)
10:03:22,476 ERROR [stderr] (MSC service thread 1-5) at java.lang.Thread.run(Thread.java:662)
Dump without JPA
10:08:22,135 ERROR [stderr] (Remoting "ws048059" task-2) java.lang.Exception: Stack trace
10:08:22,135 ERROR [stderr] (Remoting "ws048059" task-2) at java.lang.Thread.dumpStack(Thread.java:1249)
10:08:22,135 ERROR [stderr] (Remoting "ws048059" task-2) at com.siemag.model.Employee.getDefaultTestValue(Employee.java:65)
10:08:22,135 ERROR [stderr] (Remoting "ws048059" task-2) at com.siemag.model.Employee.<init>(Employee.java:25)
10:08:22,135 ERROR [stderr] (Remoting "ws048059" task-2) at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
10:08:22,150 ERROR [stderr] (Remoting "ws048059" task-2) at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:39)
10:08:22,150 ERROR [stderr] (Remoting "ws048059" task-2) at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:27)
10:08:22,150 ERROR [stderr] (Remoting "ws048059" task-2) at java.lang.reflect.Constructor.newInstance(Constructor.java:513)
10:08:22,150 ERROR [stderr] (Remoting "ws048059" task-2) at org.jboss.marshalling.reflect.ReflectiveCreator.create(ReflectiveCreator.java:107)
10:08:22,150 ERROR [stderr] (Remoting "ws048059" task-2) at org.jboss.marshalling.river.RiverUnmarshaller.doReadNewObject(RiverUnmarshaller.java:1232)
10:08:22,150 ERROR [stderr] (Remoting "ws048059" task-2) at org.jboss.marshalling.river.RiverUnmarshaller.doReadObject(RiverUnmarshaller.java:272)
10:08:22,150 ERROR [stderr] (Remoting "ws048059" task-2) at org.jboss.marshalling.river.RiverUnmarshaller.doReadObject(RiverUnmarshaller.java:209)
10:08:22,150 ERROR [stderr] (Remoting "ws048059" task-2) at org.jboss.marshalling.AbstractObjectInput.readObject(AbstractObjectInput.java:37)
10:08:22,150 ERROR [stderr] (Remoting "ws048059" task-2) at org.jboss.as.ejb3.remote.protocol.versionone.MethodInvocationMessageHandler.processMessage(MethodInvocationMessageHandler.java:156)
10:08:22,166 ERROR [stderr] (Remoting "ws048059" task-2) at org.jboss.as.ejb3.remote.protocol.versionone.VersionOneProtocolChannelReceiver.handleMessage(VersionOneProtocolChannelReceiver.java:170)
10:08:22,166 ERROR [stderr] (Remoting "ws048059" task-2) at org.jboss.remoting3.remote.RemoteConnectionChannel$5.run(RemoteConnectionChannel.java:435)
10:08:22,166 ERROR [stderr] (Remoting "ws048059" task-2) at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:886)
10:08:22,166 ERROR [stderr] (Remoting "ws048059" task-2) at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:908)
10:08:22,166 ERROR [stderr] (Remoting "ws048059" task-2) at java.lang.Thread.run(Thread.java:662)
-
8. Re: Jboss Remoting (7.1.0.Final ) and java transient fields.
suikast42 Mar 6, 2012 4:12 AM (in response to suikast42)So I would say this is definitely an ejb-remoting isue.
My testcode is shown below:
// with JPA
@Override
public <T extends BusinessObject> T getById(Class<? extends T> clazz, Long id){
return em.find(clazz, id);
}
// without JPA
@Override
public BusinessObject saveGetObjWithoutJPA(BusinessObject obj){
return obj;
}
My testcases:
@Test
public void testJPA(){
Employee emp = new Employee();
emp.setName("EmplName");
Assert.assertEquals("DEFAULT", emp.getTestString());
emp.setTestString("TestNew");
Assert.assertEquals("TestNew", emp.getTestString());
BusinessObject empNew = service.saveGetObj(emp);
Assert.assertNull(empNew.getTestString());
}
@Test
public void testWithoutJPA(){
Employee emp = new Employee();
emp.setName("EmplName");
Assert.assertEquals("DEFAULT", emp.getTestString());
emp.setTestString("TestNew");
Assert.assertEquals("TestNew", emp.getTestString());
BusinessObject empNew = service.saveGetObjWithoutJPA(emp);
Assert.assertNull(empNew.getTestString());
}
Both goes wrong.
-
9. Re: Jboss Remoting (7.1.0.Final ) and java transient fields.
smarlow Mar 6, 2012 10:12 AM (in response to suikast42)You said that both are wrong, why is the JPA case not meeting what you would expect?
For the remoting case, I'm not sure at this point but it is good to have the actual call stack showing that org.jboss.marshalling.reflect.ReflectiveCreator.create is creating a new instance, which is different than you are expecting.
From a serialization point of view, I understand that transient fields are handled differently. I'm not sure where the expected behavior is best documented, so links (or Java language spec section) are welcome. This bug report mentions that the expected behaviour should be documented (not sure if that happened or where). The following quote is from this bug report:
Perhaps the aspect that many users find most confusing is the fact that instance field initializers for non-serializable (transient) instance fields are not executed upon deserialization, just like how constructors aren't-- perhaps this fact should be emphasized more explicitly and obviously in the appropriate documentation, so that the reported behavior is less likely to seem "unpredictable".
Scott
-
10. Re: Jboss Remoting (7.1.0.Final ) and java transient fields.
suikast42 Mar 7, 2012 4:11 AM (in response to smarlow)Scott Marlow schrieb:
You said that both are wrong, why is the JPA case not meeting what you would expect?
I expect that the transient fields are null after the (de)serialisation. That was so for the previous versions of jboss. My testcase "Assert.assertNull(empNew.getTestString());" is right in jboss 5 and jboss 6 environment.. But going wrong for 7.1.0.Final.
-
11. Re: Jboss Remoting (7.1.0.Final ) and java transient fields.
smarlow Mar 7, 2012 10:03 AM (in response to suikast42)Do you have the call stack output from AS5 or AS6 that you could share here. For both the JPA and non-JPA tests.
-
12. Re: Jboss Remoting (7.1.0.Final ) and java transient fields.
suikast42 Mar 7, 2012 5:27 PM (in response to smarlow)No that was As 7.1.0.Final. But the same testcase is right in As 5.1.0.GA and AS 6.1.0.Final.
-
13. Re: Jboss Remoting (7.1.0.Final ) and java transient fields.
smarlow Mar 7, 2012 6:47 PM (in response to suikast42)The output from calling Thread.dumpStack on 5.1.0.GA or 6.1.0.Final, would of been interesting. From the point of view of comparing what happened in earlier AS releases versus now.
-
14. Re: Jboss Remoting (7.1.0.Final ) and java transient fields.
smarlow Mar 7, 2012 11:18 PM (in response to smarlow)I think that the rules that you can depend on for JPA, would be as follows. Entity class fields that are tagged with @Transient, will not be persisted to the database but will be included when the entity is serialized for transfer to another (or same) Java process. Entity class fields that are tagged with transient, will not be persisted to the database and will not be included when the entity is serialized for transfer to another Java process.
My guess is that the behaviour that you saw before, was due to byte code generation that generated the entity class proxy. If you have time to dig in deeper, I'd be interested in the results of a few more tests with AS 7.1.0.Final.
- Set property hibernate.ejb.use_class_enhancer to true in your persistence.xml (<property name="hibernate.ejb.use_class_enhancer" value="true"/>). This should cause each entity class to have a proxy generated for it (during deployment). This can change other things for your application, so I only suggest this to see if it changes your JPA test result.
- Use the Hibernate 3.6.6.Final jars instead of Hibernate 4.0.1 and see if the JPA tests results are different. I can give more guidance on this test, if your interested in trying this.