Reputation: 1801
I am trying to send a date from flex side to java using BlazeDS
field type in flex
private var _scheduleDate:Date;
I have initialized it with new Date()
, and if alert it, correct date and time is displayed as on my system. now when the object is sent to java. the date get changed.
Please note that my flex application and java (JBoss server is running on same machine). If i independently print a date on java side initialized with new Date()
, it also display correct date as of the system.
Now conversion part: on flex it was
25/04/2013 12:30 PM (as Alert displayed)
when i print this passed date(at java side), its
25/04/2013 02:30 PM (2 hours difference)
I have read many blogs etc for the solution, they refer it a time zone issue, but i didnt get it, if client and server are both on single system, how could time zone issue causes this problem.
Alert(flex)
and println(java)
with new Date()
display correct date as of the system, so how that timezone issue comes in. only i can think of is, BlazeDS is causing this issue.
Here in this link they have refered some custom marshling for blazeDS but it went above my head Custom Marshalling from Java to Flex via BlazeDS
Right now i have only one solution for this problem to send date in String
as plain text instead of Date
object and convert String
back to Date
object on java side.
Is there any better solution or if there is any issue with my understanding can someone please point out that.
Thanks,
Upvotes: 2
Views: 2444
Reputation: 1
In addition create another class for compatibility with previous versions of Java:
package br.com.ultreia.flex;
import java.io.OutputStream;
import flex.messaging.io.MessageIOConstants;
import flex.messaging.io.SerializationContext;
import flex.messaging.io.amf.AmfTrace;
public class Java15AmfMessageSerializer extends flex.messaging.io.amf.Java15AmfMessageSerializer{
@Override
public void initialize(SerializationContext context, OutputStream out, AmfTrace trace) {
amfOut = new AMF0Output(context);
amfOut.setOutputStream(out);
amfOut.setAvmPlus(version >= MessageIOConstants.AMF3);
debugTrace = trace;
isDebug = trace != null;
amfOut.setDebugTrace(debugTrace);
}
}
And I changed the class AMFEndpoint.java
public class AMFEndpoint extends flex.messaging.endpoints.AMFEndpoint {
public AMFEndpoint(){
super();
}
@Override
protected String getSerializerClassName() {
return Serializer.class.getName();
}
@Override
protected String getSerializerJava15ClassName() {
return Java15AmfMessageSerializer.class.getName();
}
@Override
protected String getDeserializerClassName() {
return Deserializer.class.getName();
}
}
Upvotes: 0
Reputation: 7294
I suggest the following solution.
First, send client timezone offset and store it as a session attribute.
ro.setClientTimezoneOffset(-new Date().getTimezoneOffset() * 60 * 1000);
public void setClientTimezoneOffset(Long t) {
FlexContext.getFlexSession().setAttribute("clientTimezoneOffset", t);
}
Create our own endpoint class extending flex.messaging.endpoints.AMFEndpoint
and point it at channel definition:
<channel-definition id="my-amf"
class="mx.messaging.channels.AMFChannel">
<endpoint url="http://{server.name}:{server.port}/{context.root}/messagebroker/amf"
class="com.package.AMFEndpoint"/>
</channel-definition>
package com.package;
public class AMFEndpoint extends flex.messaging.endpoints.AMFEndpoint {
@Override
protected String getSerializerClassName() {
return Serializer.class.getName();
}
@Override
protected String getDeserializerClassName() {
return Deserializer.class.getName();
}
}
Extend amf serializer, deserializer, amf input/output:
package com.package;
import flex.messaging.io.MessageIOConstants;
import flex.messaging.io.SerializationContext;
import flex.messaging.io.amf.AmfMessageSerializer;
import flex.messaging.io.amf.AmfTrace;
import java.io.OutputStream;
public class Serializer extends AmfMessageSerializer {
@Override
public void initialize(SerializationContext context, OutputStream out, AmfTrace trace) {
amfOut = new AMF0Output(context);
amfOut.setOutputStream(out);
amfOut.setAvmPlus(version >= MessageIOConstants.AMF3);
debugTrace = trace;
isDebug = trace != null;
amfOut.setDebugTrace(debugTrace);
}
}
package com.package;
import flex.messaging.io.SerializationContext;
import flex.messaging.io.amf.AmfMessageDeserializer;
import flex.messaging.io.amf.AmfTrace;
import java.io.InputStream;
public class Deserializer extends AmfMessageDeserializer {
@Override
public void initialize(SerializationContext context, InputStream in, AmfTrace trace) {
amfIn = new AMF0Input(context);
amfIn.setInputStream(in);
debugTrace = trace;
isDebug = debugTrace != null;
amfIn.setDebugTrace(debugTrace);
}
}
package com.package;
import flex.messaging.io.SerializationContext;
import flex.messaging.io.amf.Amf0Input;
import java.io.IOException;
public class AMF0Input extends Amf0Input {
public AMF0Input(SerializationContext context) {
super(context);
}
@Override
public Object readObject() throws ClassNotFoundException, IOException {
if (avmPlusInput == null) {
avmPlusInput = new AMF3Input(context);
avmPlusInput.setDebugTrace(trace);
avmPlusInput.setInputStream(in);
}
return super.readObject();
}
}
package com.package;
import flex.messaging.io.SerializationContext;
import flex.messaging.io.amf.Amf0Output;
public class AMF0Output extends Amf0Output {
public AMF0Output(SerializationContext context) {
super(context);
}
@Override
protected void createAMF3Output()
{
avmPlusOutput = new AMF3Output(context);
avmPlusOutput.setOutputStream(out);
avmPlusOutput.setDebugTrace(trace);
}
}
And finally you extend amf 3 input/output classes, where date is serialized and deserialized. You apply offset difference.
package com.package;
import flex.messaging.FlexContext;
import flex.messaging.io.SerializationContext;
import flex.messaging.io.amf.Amf3Input;
import java.io.IOException;
import java.util.Date;
public class AMF3Input extends Amf3Input {
@Override
protected Date readDate() throws IOException {
Date d = super.readDate();
if (d != null) {
Long clientOffset = (Long) FlexContext.getFlexSession().getAttribute("clientTimezoneOffset");
Long serverOffset = (Long) (-d.getTimezoneOffset() * 60L * 1000);
d.setTime(d.getTime() - (serverOffset - clientOffset));
}
return d;
}
public AMF3Input(SerializationContext context) {
super(context);
}
}
package com.package;
import flex.messaging.FlexContext;
import flex.messaging.io.SerializationContext;
import flex.messaging.io.amf.Amf3Output;
import java.io.IOException;
import java.util.Date;
public class AMF3Output extends Amf3Output {
public AMF3Output(SerializationContext context) {
super(context);
}
@Override
protected void writeAMFDate(Date d) throws IOException {
if (d != null) {
Long clientOffset = (Long) FlexContext.getFlexSession().getAttribute("clientTimezoneOffset");
Long serverOffset = (Long) (-d.getTimezoneOffset() * 60L * 1000);
d.setTime(d.getTime() + (serverOffset - clientOffset));
}
super.writeAMFDate(d);
}
}
Now all dates, passed between Flex front-end and BlazeDS back-end will be automatically converted. Note, that you actually change the date.
Assume server time zone is GMT+6, and client is in GMT+2 timezome.
You're retrieving date from database. The date on java is 01.01.2013 10.00.00 GMT+6
, normally flex would get 01.01.2013 06.00.00 GMT+2
. It's the same date, but String equivalent differs. In our case flex will get 01.01.2013 10.00.00 GMT+2
. We changed the date. But string equivalent is the same.
Upvotes: 2