[Logo] Terracotta Discussion Forums
  [Search] Search   [Recent Topics] Recent Topics   [Members]  Member Listing   [Groups] Back to home page 
[Register] Register / 
[Login] Login 
[Expert]
Using TC with joda-time  XML
Forum Index -> Terracotta Platform Go to Page: 1, 2, 3 Next 
Author Message
mpvvliet

neo

Joined: 05/30/2007 03:52:01
Messages: 2
Offline

Hi all,

we are trying to cluster our application using TC. The application uses the joda-time library to represent dates. This library seems to have a lot of transient data, so to make it work we set the honor transient flag to false for joda-time classes. However, this leads to the following error:

Code:
 java.lang.ClassCastException: ReadablePartial objects must have matching field types
         at org.joda.time.base.AbstractPartial.compareTo(AbstractPartial.java:325)
         at nl.prorail.pub.dvs.TrainDepartureMessage.compareTo(TrainDepartureMessage.java:127)
         at nl.prorail.pub.dvs.TrainDepartureMessage.compareTo(TrainDepartureMessage.java:31)
         at java.util.Arrays.mergeSort(Arrays.java:1156)
         at java.util.Arrays.sort(Arrays.java:1080)
         at java.util.Collections.sort(Collections.java:117)
         at nl.prorail.pub.display.Tb7xController.createPublications(Tb7xController.java:90)
         at nl.prorail.pub.display.Tb7xController.messageReceived(Tb7xController.java:79)
         at nl.prorail.pub.dvs.TrainDepartureMessage.accept(TrainDepartureMessage.java:363)
         at nl.prorail.pub.display.DisplayController.messageReceived(DisplayController.java:33)
         at nl.prorail.pub.distribution.Station.messageReceived(Station.java:31)
         at nl.prorail.pub.service.PubServiceImpl.messageReceived(PubServiceImpl.java:40)
         at nl.prorail.pub.service.DvsMessageListener.onMessage(DvsMessageListener.java:45)
         at org.springframework.jms.listener.AbstractMessageListenerContainer.doInvokeListener(AbstractMessageListenerContainer.java:854)
         at org.springframework.jms.listener.AbstractMessageListenerContainer.invokeListener(AbstractMessageListenerContainer.java:793)
         at org.springframework.jms.listener.AbstractMessageListenerContainer.doExecuteListener(AbstractMessageListenerContainer.java:763)
         at org.springframework.jms.listener.DefaultMessageListenerContainer.doReceiveAndExecute(DefaultMessageListenerContainer.java:513)
         at org.springframework.jms.listener.DefaultMessageListenerContainer.receiveAndExecute(DefaultMessageListenerContainer.java:460)
         at org.springframework.jms.listener.DefaultMessageListenerContainer$AsyncMessageListenerInvoker.invokeListener(DefaultMessageListenerContainer.java:871)
         at org.springframework.jms.listener.DefaultMessageListenerContainer$AsyncMessageListenerInvoker.run(DefaultMessageListenerContainer.java:824)
         at org.springframework.core.task.SimpleAsyncTaskExecutor$ConcurrencyThrottlingRunnable.run(SimpleAsyncTaskExecutor.java:203)
         at java.lang.Thread.run(Thread.java:595)
 


Honoring transient leads to NPE's so this is also not an option. A custom on-load element might work, but we haven't found the right way to (re)initialize these fields yet.

Has anyone gotten TC to work with joda-time? Any help would be appreciated.

Thanks,
Martin
kbhasin

consul

Joined: 12/04/2006 13:08:21
Messages: 340
Offline

Hi mpvvliet,

I am not sure if anyone has tried to cluster joda-time with Terracotta.

Are you getting this error on a single node or on multiple nodes?

I think what you are seeing here is that when the compareTo is called to compare the ReadablePartial implementation (some sub-class of AbstractPartial), the transient field value is null (on the second instance) and hence the resulting "field types must match" error.

The correct way to handle this would be to honor transient and use an appropriate method (e.g. bean shell) to initialize transients on the onLoad:

Code:
 <class-expression>com.mycompany.mypackage.MyClass</class-expression>
 
           <!-- If set to 'true', then any fields in the given class(es)
              that have the Java 'transient' modifier are not shared
              across JVMs. If set to 'false', they are.
 
              Default: false -->
           <honor-transient>true</honor-transient>
           <on-load>
             <!-- One of either <execute> or <method> is required within an <on-load> element -->
 
             <!-- This (zero argument) method will be called on instances of the specified class
                on load of the object. Used to intialize transient fields. You are free to use
                whatever method name you please. -->
             <!-- <method>initTransients</method> -->
 
             <!-- This bean shell script is called right after an object is loaded -->
             <execute><![CDATA[self.myTransientField = new ArrayList();]]></execute>
           </on-load>  
         </include>
 
 


Can you also point to the subclass of AbstractPartial in question here. I am assuming it should be one of the following:


class LocalDate
LocalDate is an immutable datetime class representing a date without a time zone.
class LocalDateTime
LocalDateTime is an unmodifiable datetime class representing a datetime without a time zone.
class LocalTime
LocalTime is an immutable time class representing a time without a time zone.
class Partial
Partial is an immutable partial datetime supporting any set of datetime fields.
class TimeOfDay
TimeOfDay is an immutable partial supporting the hour, minute, second and millisecond fields.
class YearMonthDay
YearMonthDay is an immutable partial supporting the year, monthOfYear and dayOfMonth fields.

Regards,
Kunal Bhasin.

Regards,

Kunal Bhasin,
Terracotta, Inc.

Be a part of the Terracotta community: Join now!
mpvvliet

neo

Joined: 05/30/2007 03:52:01
Messages: 2
Offline

Hi Kunal.

it is an instance of the LocalTime class. I have tested this only with 1 node. After processing some data, the TC server holds the clustered instances. Then I restart the node and the application attempts to retrieve & modify the data contained in TC. This is when the error occurs. I assume the same will happen with 2 nodes when they share data, but I have not verified this.

I tried calling a Beanshell initialization method (setFields()) like so:

Code:
         <include>
 <class-expression>org.joda.time.chrono.AssembledChronology</class-expression>
           <honor-transient>true</honor-transient>
           <on-load>
             <execute>self.setFields();</execute>
           </on-load>
         </include>
 


but this did not fix anything, the same error still occurred. Perhaps I am using the wrong BS syntax?

Regards,
Martin
kbhasin

consul

Joined: 12/04/2006 13:08:21
Messages: 340
Offline

Hi Martin,

Can you try the following syntax:

Code:
 <on-load>
                         <!-- This bean shell script is called right after an object is loaded -->
                    <execute><![CDATA[self.myTransientField = new ArrayList();]]></execute>
             </on-load>
 


If you have access to code, you can also add a custom method in your code to initialize transients:

Code:
 <on-load>
                         <!-- This (zero argument) method will be called on instances of the specified class
                            on load of the object. Used to intialize transient fields. You are free to use
                            whatever method name you please. -->
                    <method>initTransients</method>
                    <!-- e.g. The method in your code would look like this -
                                 public void initTransients() {
                                      myTransientField = new ArrayList();
                                 }
                    --> 
 </on-load>
 


Also, the <on-load> property should be paired with the <include> of the class containing the transient field or a wildcard [ e.g. mypackage..* ] that includes the class containing the transient.

In your case, I am not sure if it wil be LocalTime or AssembledChronology.

Regards,
Kunal Bhasin.



Regards,

Kunal Bhasin,
Terracotta, Inc.

Be a part of the Terracotta community: Join now!
Shake

master

Joined: 01/05/2008 07:27:49
Messages: 84
Offline

Okay, I run into the same problem.
I tried

Code:
 
 <include>         <class-expression>org.joda.time.chrono.AssembledChronology</class-expression>
           <honor-transient>true</honor-transient>
           <on-load>
             <execute><![CDATA[self.setFields();]]></execute>
           </on-load>
         </include>
 


which doesn't solve my problem. Any hints? Had anyone success using Joda Time and Terracotta?
Shake

master

Joined: 01/05/2008 07:27:49
Messages: 84
Offline

Investigated further:
There seems to exist a problem with object identity.


At org.joda.time.base.AbstractPartial.compareTo(AbstractPartial.java:325)
there are tow org.joda.time.DateTimeFieldType compared using "!=".

I don't know why this fails - but while the fields represent the same thing (month, year...) they have lost the object identity...
Shake

master

Joined: 01/05/2008 07:27:49
Messages: 84
Offline

Okay, I have found a solution:
Code:
 <roots>
         <root>
           <field-name>org.joda.time.DateTimeFieldType.ERA_TYPE</field-name>
         </root>
         <root>
           <field-name>org.joda.time.DateTimeFieldType.YEAR_OF_ERA_TYPE</field-name>
         </root>
         <root>
           <field-name>org.joda.time.DateTimeFieldType.CENTURY_OF_ERA_TYPE</field-name>
         </root>
 



Since I could't find a valid field-expression, I had to add every single field...

tgautier

seraphim

Joined: 06/05/2006 12:19:26
Messages: 1781
Offline

Neat. When you have a working prototype, maybe you would like some help turning it into a TIM?
[WWW]
Shake

master

Joined: 01/05/2008 07:27:49
Messages: 84
Offline

And one more issue: The method org.joda.time.tz.CachedDateTimeZone#getInfo is not synchronized, but I think it should be (for terracotta).

I tried to add a named lock, but this didn't work as expected... Either I defined the named lock wrong or adding the lock doesn't solve the issue.

Same goes for org.joda.time.chrono.BasicChronology#getYearInfo.


Could you provide give me a hint how a name lock should look like? And show an example of the field-expression that matches all the static fields of a given type within a given class?
ekulesho

master

Joined: 12/04/2006 08:49:08
Messages: 57
Offline

Shake wrote:
... Since I could't find a valid field-expression, I had to add every single field... 
Documentation for the expression language is here. So you can try something like this:

Code:
<field-expression>* org.joda.time.DateTimeFieldType org.joda.time.DateTimeFieldType.*</field-expression>
regards,
Eugene Kuleshov
[WWW]
Shake

master

Joined: 01/05/2008 07:27:49
Messages: 84
Offline

Yes, tried that already:

Code:
 
 [INFO] [bootjar] com.tc.aspectwerkz.exception.DefinitionException: expression is not well-formed [get(* org.joda.time.DateTimeFieldType org.joda.time.DateTimeFieldType.*)]: Encountered "org.joda.time.DateTimeFieldType.*" at line 1, column 39.
 [INFO] [bootjar] Was expecting:
 [INFO] [bootjar]     ")" ...
 [INFO] [bootjar]     
 [INFO] [bootjar]        at com.tc.aspectwerkz.expression.ExpressionInfo.<init>(ExpressionInfo.java:92)
 [INFO] [bootjar]        at com.tc.object.bytecode.aspectwerkz.ExpressionHelper.createExpressionInfo(ExpressionHelper.java:61)
 [INFO] [bootjar]        at com.tc.object.bytecode.aspectwerkz.ExpressionHelper.createExpressionInfo(ExpressionHelper.java:49)
 [INFO] [bootjar]        at com.tc.object.bytecode.aspectwerkz.ExpressionHelper.createExpressionVisitor(ExpressionHelper.java:41)
 [INFO] [bootjar]        at com.tc.object.config.Root.matches(Root.java:93)
 [INFO] [bootjar]        at com.tc.object.config.StandardDSOClientConfigHelperImpl.findMatchingRootDefinition(StandardDSOClientConfigHelperImpl.java:1232)
 [INFO] [bootjar]        at com.tc.object.config.StandardDSOClientConfigHelperImpl.classContainsAnyRoots(StandardDSOClientConfigHelperImpl.java:1241)
 [INFO] [bootjar]        at com.tc.object.config.StandardDSOClientConfigHelperImpl.shouldBeAdapted(StandardDSOClientConfigHelperImpl.java:1437)
 [INFO] [bootjar]        at com.tc.object.config.TransparencyClassSpecImpl.hasPhysicallyPortableSpecs(TransparencyClassSpecImpl.java:88)
 [INFO] [bootjar]        at com.tc.object.bytecode.InstrumentationSpec.isNeedManagedField(InstrumentationSpec.java:238)
 [INFO] [bootjar]        at com.tc.object.bytecode.InstrumentationSpec.decideOnInstrumentationsToDo(InstrumentationSpec.java:223)
 [INFO] [bootjar]        at com.tc.object.bytecode.InstrumentationSpec.decideOnInstrumentationAction(InstrumentationSpec.java:212)
 [INFO] [bootjar]        at com.tc.object.bytecode.InstrumentationSpec.initialize(InstrumentationSpec.java:121)
 [INFO] [bootjar]        at com.tc.object.bytecode.ClassAdapterBase.visit(ClassAdapterBase.java:105)
 [INFO] [bootjar]        at com.tc.object.bytecode.MergeTCToJavaClassAdapter.visit(MergeTCToJavaClassAdapter.java:129)
 [INFO] [bootjar]        at com.tc.asm.ClassAdapter.visit(ClassAdapter.java:63)
 [INFO] [bootjar]        at com.tc.asm.commons.SerialVersionUIDAdder.visit(SerialVersionUIDAdder.java:199)
 [INFO] [bootjar]        at com.tc.asm.ClassReader.accept(ClassReader.java:553)
 [INFO] [bootjar]        at com.tc.asm.ClassReader.accept(ClassReader.java:420)
 [INFO] [bootjar]        at com.tc.object.tools.BootJarTool.mergeClass(BootJarTool.java:2208)
 [INFO] [bootjar]        at com.tc.object.tools.BootJarTool.mergeClass(BootJarTool.java:2165)
 [INFO] [bootjar]        at com.tc.object.tools.BootJarTool.addInstrumentedHashMap(BootJarTool.java:2159)
 [INFO] [bootjar]        at com.tc.object.tools.BootJarTool.generateJar(BootJarTool.java:402)
 [INFO] [bootjar]        at com.tc.object.tools.BootJarTool.main(BootJarTool.java:2532)
 [INFO] [bootjar] com.tc.aspectwerkz.expression.ast.ParseException: Encountered "org.joda.time.DateTimeFieldType.*" at line 1, column 39.
 [INFO] [bootjar] Was expecting:
 [INFO] [bootjar]     ")" ...
 [INFO] [bootjar]     
 [INFO] [bootjar]        at com.tc.aspectwerkz.expression.ast.ExpressionParser.generateParseException(ExpressionParser.java:3521)
 [INFO] [bootjar]        at com.tc.aspectwerkz.expression.ast.ExpressionParser.jj_consume_token(ExpressionParser.java:3391)
 [INFO] [bootjar]        at com.tc.aspectwerkz.expression.ast.ExpressionParser.Get(ExpressionParser.java:739)
 [INFO] [bootjar]        at com.tc.aspectwerkz.expression.ast.ExpressionParser.Pointcut(ExpressionParser.java:315)
 [INFO] [bootjar]        at com.tc.aspectwerkz.expression.ast.ExpressionParser.UnaryExpression(ExpressionParser.java:246)
 [INFO] [bootjar]        at com.tc.aspectwerkz.expression.ast.ExpressionParser.OrExpression(ExpressionParser.java:177)
 [INFO] [bootjar]        at com.tc.aspectwerkz.expression.ast.ExpressionParser.AndExpression(ExpressionParser.java:131)
 [INFO] [bootjar]        at com.tc.aspectwerkz.expression.ast.ExpressionParser.Expression(ExpressionParser.java:93)
 [INFO] [bootjar]        at com.tc.aspectwerkz.expression.ast.ExpressionParser.Root(ExpressionParser.java:49)
 [INFO] [bootjar]        at com.tc.aspectwerkz.expression.ast.ExpressionParser.parse(ExpressionParser.java:35)
 [INFO] [bootjar]        at com.tc.aspectwerkz.expression.ast.ExpressionParser.parse(ExpressionParser.java:30)
 [INFO] [bootjar]        at com.tc.aspectwerkz.expression.ExpressionInfo.<init>(ExpressionInfo.java:85)
 [INFO] [bootjar]        at com.tc.object.bytecode.aspectwerkz.ExpressionHelper.createExpressionInfo(ExpressionHelper.java:61)
 [INFO] [bootjar]        at com.tc.object.bytecode.aspectwerkz.ExpressionHelper.createExpressionInfo(ExpressionHelper.java:49)
 [INFO] [bootjar]        at com.tc.object.bytecode.aspectwerkz.ExpressionHelper.createExpressionVisitor(ExpressionHelper.java:41)
 [INFO] [bootjar]        at com.tc.object.config.Root.matches(Root.java:93)
 [INFO] [bootjar]        at com.tc.object.config.StandardDSOClientConfigHelperImpl.findMatchingRootDefinition(StandardDSOClientConfigHelperImpl.java:1232)
 [INFO] [bootjar]        at com.tc.object.config.StandardDSOClientConfigHelperImpl.classContainsAnyRoots(StandardDSOClientConfigHelperImpl.java:1241)
 [INFO] [bootjar]        at com.tc.object.config.StandardDSOClientConfigHelperImpl.shouldBeAdapted(StandardDSOClientConfigHelperImpl.java:1437)
 [INFO] [bootjar]        at com.tc.object.config.TransparencyClassSpecImpl.hasPhysicallyPortableSpecs(TransparencyClassSpecImpl.java:88)
 [INFO] [bootjar]        at com.tc.object.bytecode.InstrumentationSpec.isNeedManagedField(InstrumentationSpec.java:238)
 [INFO] [bootjar]        at com.tc.object.bytecode.InstrumentationSpec.decideOnInstrumentationsToDo(InstrumentationSpec.java:223)
 [INFO] [bootjar]        at com.tc.object.bytecode.InstrumentationSpec.decideOnInstrumentationAction(InstrumentationSpec.java:212)
 [INFO] [bootjar]        at com.tc.object.bytecode.InstrumentationSpec.initialize(InstrumentationSpec.java:121)
 [INFO] [bootjar]        at com.tc.object.bytecode.ClassAdapterBase.visit(ClassAdapterBase.java:105)
 [INFO] [bootjar]        at com.tc.object.bytecode.MergeTCToJavaClassAdapter.visit(MergeTCToJavaClassAdapter.java:129)
 [INFO] [bootjar]        at com.tc.asm.ClassAdapter.visit(ClassAdapter.java:63)
 [INFO] [bootjar]        at com.tc.asm.commons.SerialVersionUIDAdder.visit(SerialVersionUIDAdder.java:199)
 [INFO] [bootjar]        at com.tc.asm.ClassReader.accept(ClassReader.java:553)
 [INFO] [bootjar]        at com.tc.asm.ClassReader.accept(ClassReader.java:420)
 [INFO] [bootjar]        at com.tc.object.tools.BootJarTool.mergeClass(BootJarTool.java:2208)
 [INFO] [bootjar]        at com.tc.object.tools.BootJarTool.mergeClass(BootJarTool.java:2165)
 [INFO] [bootjar]        at com.tc.object.tools.BootJarTool.addInstrumentedHashMap(BootJarTool.java:2159)
 [INFO] [bootjar]        at com.tc.object.tools.BootJarTool.generateJar(BootJarTool.java:402)
 [INFO] [bootjar]        at com.tc.object.tools.BootJarTool.main(BootJarTool.java:2532)
 [INFO] [bootjar] 
 [INFO] [bootjar] *************** ERROR ***************
 [INFO] [bootjar] * ERROR creating temp boot jar
 [INFO] [bootjar] *************************************
 [INFO] [bootjar] 
 
 


for

Code:
      <roots>
         <root>
           <field-expression>* org.joda.time.DateTimeFieldType org.joda.time.DateTimeFieldType.*</field-expression>
           <root-name>theName</root-name>
         </root>
       </roots>
 
 

tgautier

seraphim

Joined: 06/05/2006 12:19:26
Messages: 1781
Offline

Shake wrote:
And one more issue: The method org.joda.time.tz.CachedDateTimeZone#getInfo is not synchronized, but I think it should be (for terracotta).
 


Maybe an auto-synchronized would be better:

Code:
 <autolock auto-synchronized="true">
   <method-expression>* org.joda.time.tz.CachedDateTimeZone.getInfo(..)</method-expression>
 </autolock>
 
[WWW]
tgautier

seraphim

Joined: 06/05/2006 12:19:26
Messages: 1781
Offline

ekulesho wrote:

Shake wrote:
... Since I could't find a valid field-expression, I had to add every single field... 
Documentation for the expression language is here. So you can try something like this:

Code:
<field-expression>* org.joda.time.DateTimeFieldType org.joda.time.DateTimeFieldType.*</field-expression>
regards,
Eugene Kuleshov 


This would work if you want every field in DateTimeFieldType - however if there are fields that shouldn't be roots this might be over-broad.
[WWW]
tgautier

seraphim

Joined: 06/05/2006 12:19:26
Messages: 1781
Offline

Shake wrote:
Yes, tried that already:

for

Code:
      <roots>
         <root>
           <field-expression>* org.joda.time.DateTimeFieldType org.joda.time.DateTimeFieldType.*</field-expression>
           <root-name>theName</root-name>
         </root>
       </roots>
 
 

 


Hmm, I think the root-name would try to make all of the fields the same root, which would be bad (basically they would all be forced to be the same object). That *should* work if you take the root-name spec out, however as I say in my previous post, only if you want every field in DateTimeFieldType to be a root.
[WWW]
ekulesho

master

Joined: 12/04/2006 08:49:08
Messages: 57
Offline

Shake wrote:
Yes, tried that already:Code:
      <roots>
         <root>
           <field-expression>* org.joda.time.DateTimeFieldType org.joda.time.DateTimeFieldType.*</field-expression>
           <root-name>theName</root-name>
         </root>
       </roots>
 
 
Indeed. It seems like parser doesn't like when * is used in the modifiers slot. I've tried this variant and it is at least accepted by the expression parser:

Code:
<field-expression>private static final org.joda.time.DateTimeFieldType org.joda.time.DateTimeFieldType.*</field-expression>
regards,
Eugene Kuleshov
[WWW]
 
Forum Index -> Terracotta Platform Go to Page: 1, 2, 3 Next 
Go to:   
Powered by JForum 2.1.7 © JForum Team