What is the possible error for this retrofit code? I can't understand the connection of my API and MOBILE - json

I would like to find out the error is from my code or from my api.
This is my API CLASS:
import retrofit2.Call;
import retrofit2.http.Body;
import retrofit2.http.POST;
public interface Api {
#POST("/api/Database/NewLocation")
Call<MapDetails> mapDetailLocation(#Body MapDetails mapDetails);
#POST("/api/Registration/RegisterDevice")
Call<RegisterDetails> registerDetails(#Body RegisterDetails
registerAllDetails);
}
SETTER CLASS:
import com.google.gson.annotations.SerializedName;
public class MapDetails {
#SerializedName("SerialNumber")
private String serialNumber;
#SerializedName("Coordinate1")
private String coordinate1;
#SerializedName("Coordinate2")
private String coordinate2;
#SerializedName("DateTime")
private String dateTime;
#SerializedName("Speed")
private String speed;
#SerializedName("Port")
private Integer Port;
public MapDetails(String serialNumber, String coordinate1, String
coordinate2,
String dateTime, String speed, Integer port) {
this.serialNumber = serialNumber;
this.coordinate1 = coordinate1;
this.coordinate2 = coordinate2;
this.dateTime = dateTime;
this.speed = speed;
Port = port;
}
public String getSerialNumber() {
return serialNumber;
}
public void setSerialNumber(String serialNumber) {
this.serialNumber = serialNumber;
}
public String getCoordinate1() {
return coordinate1;
}
public void setCoordinate1(String coordinate1) {
this.coordinate1 = coordinate1;
}
public String getCoordinate2() {
return coordinate2;
}
public void setCoordinate2(String coordinate2) {
this.coordinate2 = coordinate2;
}
public String getDateTime() {
return dateTime;
}
public void setDateTime(String dateTime) {
this.dateTime = dateTime;
}
public String getSpeed() {
return speed;
}
public void setSpeed(String speed) {
this.speed = speed;
}
public Integer getPort() {
return Port;
}
public void setPort(Integer port) {
Port = port;
}
}
Activity Class:
MapDetails mapDetails = new MapDetails("1807200005",
lat,lon, currentDateTimeString, "0", 9090);
setLocation(mapDetails);
private void setLocation(MapDetails mapDetails) {
initializeRetrofit(mapDetails);
}
private void initializeRetrofit(MapDetails mapDetails) {
Retrofit.Builder builder = new Retrofit.Builder()
.baseUrl("http://undefine.apisecure.data[![enter image description here][1]][1]")
.addConverterFactory(GsonConverterFactory.create());
Retrofit retrofit = builder.build();
Api locate = retrofit.create(Api.class);
SetMapLocationApiCaller(locate, mapDetails);
}
private void SetMapLocationApiCaller(Api locate, MapDetails
mapDetails) {
Call<MapDetails> call =
locate.mapDetailLocation(mapDetails);
executeCallAsynchronously(call);
}
private void executeCallAsynchronously(Call call) {
call.enqueue(new Callback<MapDetails>() {
#Override
public void onResponse(Call<MapDetails> call,
Response<MapDetails> response) {
Snackbar.make(view,""+ response,
Snackbar.LENGTH_INDEFINITE)
.setAction("Action", null).show();
}
#Override
public void onFailure(Call call, Throwable t) {
Snackbar.make(view, ""+t.getMessage(),
Snackbar.LENGTH_INDEFINITE)
.setAction("Action", null).show();
}
});
}
On my app , this is the response on my app:
but its not added to my sql. But if am using insomia, it would have send the data I've created to the database.
this data was inserted via insomia not on mobile.

You almost reached to the solution. But, you made little mistake while passing parameters to the API request.
As I can see from the screenshot of Insomia app, that API requires JSONArray as parameter but you're sending JSONObject.
Sample JSON parameter
[
{
"SerialNumber" : "1234",
"Coordinate1" : "12.7845874",
"Coordinate2" : "76.4584578",
"DateTime" : "2018-11-14 08:45:00",
"Speed" : "0",
"Port" : 9090
}
]
According to the above JSON structure you need to change the Api.java class to something like this:
import retrofit2.Call;
import retrofit2.http.Body;
import retrofit2.http.POST;
import java.util.List; // add import
public interface Api {
#POST("/api/Database/NewLocation")
Call < MapDetails > mapDetailLocation(#Body List<MapDetails> mapDetails);
// ^^^^ changes here
#POST("/api/Registration/RegisterDevice")
Call < RegisterDetails > registerDetails(#Body RegisterDetails registerAllDetails);
}
Add List<MapDetails> to mapDetailLocation() method parameter.
And in Activity or Fragment use above method like this:
//......
// part of the code
MapDetails mapDetails = new MapDetails("1807200005", lat, lon, currentDateTimeString, "0", 9090);
List<MapDetails> data = new ArrayList<>();
data.add(mapDetails);
Retrofit.Builder builder = new Retrofit.Builder()
.baseUrl("<BASE_URL>") // change base URL
.addConverterFactory(GsonConverterFactory.create());
Retrofit retrofit = builder.build();
Api locate = retrofit.create(Api.class);
Call<MapDetails> call = locate.mapDetailLocation(data); // NOTICE THE CHANGES IN PARAMETER
call.enqueue(new Callback<MapDetails>() {
#Override
public void onResponse(Call<MapDetails> call, Response<MapDetails> response) {
// do whatever you want
}
#Override
public void onFailure(Call call, Throwable t) {
// log the error message
}
});
Note: Please change base URL according to your requirement.
Edit:
Change method parameters in Activity from MapDetails to List<MapDetails>
// prepare data
MapDetails data = new MapDetails("1807200005", lat, lon, currentDateTimeString, "0", 9090);
// add it to ArrayList
List<MapDetails> mapDetails = new ArrayList<>();
mapDetails.add(data);
// pass it as an argument
private void setLocation(List<MapDetails> mapDetails) {
initializeRetrofit(mapDetails);
}
Change method parameter in initializeRetrofit()
private void initializeRetrofit(List<MapDetails> mapDetails) {
Retrofit.Builder builder = new Retrofit.Builder()
.baseUrl("<BASE_URL>") // change base URL
.addConverterFactory(GsonConverterFactory.create());
Retrofit retrofit = builder.build();
Api locate = retrofit.create(Api.class);
SetMapLocationApiCaller(locate, mapDetails);
}
Again change method parameter
private void SetMapLocationApiCaller(Api locate, List<MapDetails> mapDetails) {
Call<MapDetails> call = locate.mapDetailLocation(mapDetails);
executeCallAsynchronously(call);
}

Related

get the data in recyclerview

Hello everyone i am getting the messages of the users in android studio for that i am refreshing the recyclerview every second but the probem is scrolling when i am scrooling the recyclerview to old messages then its not scrooling becouse of the getting data every second can someone please help me in this
bellow is my activity code
public class Message_User_Activity extends AppCompatActivity {
private RecyclerView recyclerView;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_message_user);
content();
Clicks();
}
public void content()
{
getdata();
refresh(100);
}
private void refresh(int milliseconds)
{
final Handler handler = new Handler();
final Runnable runnable = new Runnable() {
#Override
public void run() {
content();
}
};
handler.postDelayed(runnable,milliseconds);
}
private void getdata()
{
toolbar_user_name.setText(name);
String Choice = "Get Messages";
Call<List<responsemodel>> call = SplashScreen.apiInterface.getfullprofiledata(Choice,Message_To,Message_From);
call.enqueue(new Callback<List<responsemodel>>() {
#Override
public void onResponse(Call<List<responsemodel>> call, Response<List<responsemodel>> response) {
List<responsemodel> data = response.body();
Message_user_Adapter adapter = new Message_user_Adapter(data,Message_To);
messages_Message_user_RecyclerView.setAdapter(adapter);
messages_Message_user_RecyclerView.scrollToPosition(messages_Message_user_RecyclerView.getAdapter().getItemCount() -1);
}
#Override
public void onFailure(Call<List<responsemodel>> call, Throwable t) {
}
});
}
}
below is my adapter code
public class Message_user_Adapter extends RecyclerView.Adapter<Message_user_Adapter.Message_user_Adapter_View_Holder>
{
List<responsemodel> data;
String mmessage_To;
public Message_user_Adapter(List<responsemodel> data, String message_To) {
this.data = data;
this.mmessage_To = message_To;
}
#NonNull
#Override
public Message_user_Adapter_View_Holder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.user_messages_layout,parent,false);
return new Message_user_Adapter_View_Holder(view);
}
#RequiresApi(api = Build.VERSION_CODES.N)
#Override
public void onBindViewHolder(#NonNull Message_user_Adapter_View_Holder holder, int position) {
String time = calculateTime(data.get(position).getMessage_Time());
if (data.get(position).getMessage_From().equals(mmessage_To))
{
holder.other_user_message_message_layout.setVisibility(View.VISIBLE);
holder.other_user_message_message_layout.setText(data.get(position).getMessage() + "\n \n" + time);
holder.message_message_layout.setVisibility(View.GONE);
}
else
{
holder.other_user_message_message_layout.setVisibility(View.GONE);
holder.message_message_layout.setText(data.get(position).getMessage() + "\n \n" + time);
holder.message_message_layout.setVisibility(View.VISIBLE);
}
}
#RequiresApi(api = Build.VERSION_CODES.N)
private String calculateTime(String post_time)
{
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss");
try {
long time = sdf.parse(post_time).getTime();
long now = System.currentTimeMillis();
CharSequence ago =
DateUtils.getRelativeTimeSpanString(time, now, DateUtils.MINUTE_IN_MILLIS);
return ago+"";
} catch (ParseException e) {
e.printStackTrace();
}
return null;
}
#Override
public int getItemCount() {
return data.size();
}
public String getdata() {
return mmessage_To.toString();
}
class Message_user_Adapter_View_Holder extends RecyclerView.ViewHolder
{
TextView other_user_message_message_layout;
TextView message_message_layout;
CircleImageView toolbar_user_profile;
public Message_user_Adapter_View_Holder(#NonNull View itemView) {
super(itemView);
other_user_message_message_layout = itemView.findViewById(R.id.other_user_message_message_layout);
message_message_layout = itemView.findViewById(R.id.message_message_layout);
}
}
}
According to my simple information
in your getdata() function. you send new data to Message_user_Adapter of RecyclerView every time you receive data from API or whatever you use ,so the data of adapter every second is change to new data ,so the RecyclerView being recreated every second with new data and the scroll will not work
just try to outage this lines from onResponse to the first of getdata():
Message_user_Adapter adapter = new Message_user_Adapter(data,Message_To);
messages_Message_user_RecyclerView.setAdapter(adapter);
and in its place add this line to notify the adapter about changed data :
adapter.notifyDatasetChanged()
something like this :
private void getdata() {
toolbar_user_name.setText(name);
String Choice = "Get Messages";
List<responsemodel> data = new ArrayList<>();//this line was change
Message_user_Adapter adapter = new Message_user_Adapter(data,Message_To);//this line was change
messages_Message_user_RecyclerView.setAdapter(adapter);//this line was change
Call<List<responsemodel>> call = SplashScreen.apiInterface.getfullprofiledata(Choice,Message_To,Message_From);
call.enqueue(new Callback<List<responsemodel>>() {
#Override
public void onResponse(Call<List<responsemodel>> call, Response<List<responsemodel>> response) {
data = response.body();
adapter.notifyDatasetChanged()//this line was added
messages_Message_user_RecyclerView.scrollToPosition(messages_Message_user_RecyclerView.getAdapter().getItemCount() -1);
}
#Override
public void onFailure(Call<List<responsemodel>> call, Throwable t) {
}
});
}

Getting an Unrecognized field "Status" (Class ektron.cms.jdbc.extractors.AssetDataResponse), not marked as ignorable error with Jersey Client API

I have the following JSON being returned from a RESTful Service
{
"Status": "Success",
"Success": true,
"Path": "D:\\Work\\Sites\\EKSites\\OnTrek\\privateassets\\0\\155\\156\\ceb3dc64-33ed-4e96-80a2-846120ecd9ee.pdf",
"Timestamp": "2013-03-27T18:35:23.8997358-04:00"
}
I am trying to deserialize the JSON into this data class:
package ektron.cms.jdbc.extractors;
#JsonPropertyOrder({ "Status", "Success", "Path", "Timestamp" })
public class AssetDataResponse {
#JsonProperty("Status")
private String Status;
#JsonProperty("Success")
private Boolean Success;
#JsonProperty("Path")
private String Path;
#JsonProperty("Timestamp")
private String Timestamp;
private Map<String, Object> additionalProperties = new HashMap<String, Object>();
#JsonProperty("Status")
public String getStatus() {
return Status;
}
#JsonProperty("Status")
public void setStatus(String Status) {
this.Status = Status;
}
#JsonProperty("Success")
public Boolean getSuccess() {
return Success;
}
#JsonProperty("Success")
public void setSuccess(Boolean Success) {
this.Success = Success;
}
#JsonProperty("Path")
public String getPath() {
return Path;
}
#JsonProperty("Path")
public void setPath(String Path) {
this.Path = Path;
}
#JsonProperty("Timestamp")
public String getTimestamp() {
return Timestamp;
}
#JsonProperty("Timestamp")
public void setTimestamp(String Timestamp) {
this.Timestamp = Timestamp;
}
#Override
public String toString() {
return ToStringBuilder.reflectionToString(this);
}
#JsonAnyGetter
public Map<String, Object> getAdditionalProperties() {
return this.additionalProperties;
}
#JsonAnySetter
public void setAdditionalProperties(String name, Object value) {
this.additionalProperties.put(name, value);
}
}
Following is my client code:
package ektron.common.network;
//...
ClientConfig clientConfig = new DefaultClientConfig();
clientConfig.getFeatures().put(JSONConfiguration.FEATURE_POJO_MAPPING, Boolean.TRUE);
clientConfig.getClasses().add(JacksonJsonProvider.class);
client = Client.create(clientConfig);
WebResource webResource =
client.resource(
String.format("http://%s:%d/%s","localhost",7605,"asset"));
String return =
webResource
.path("3f7078c4")
.path("ceb3dc64-33ed-4e96-80a2-846120ecd9ee")
.accept(MediaType.APPLICATION_JSON)
.get(String.class); //This piece works and I get my JSON response as
//indicated above
But if I change the above to:
AssetDataResponse resp =
webResource
.path("3f7078c4")
.path("ceb3dc64-33ed-4e96-80a2-846120ecd9ee")
.accept(MediaType.APPLICATION_JSON)
.get(AssetDataResponse.class);
I get the following error:
Unrecognized field "Status" (Class ektron.cms.jdbc.extractors.AssetDataResponse), not marked as ignorable
Is there any configuration on ClientConfig that I need to make to get the deserialization working correctly? Any help on this would be very much appreciated. I am .NET developer quite new to Java and am not so familiar with the Jersey framework. I have already checked the answer from a similar question and my case is different from the case listed there.
Client side Jars
annotations-1.3.9.jar
asm-3.1.jar
codemodel-2.4.1.jar
jackson-annotations-2.1.2.jar
jackson-core-2.1.3.jar
jackson-core-asl-1.9.11.jar
jackson-databind-2.1.3.jar
jackson-jaxrs-1.9.2.jar
jackson-mapper-asl-1.9.11.jar
jackson-xc-1.9.2.jar
jcommander-1.30.jar
jersey-apache-client-1.17.jar
jersey-atom-abdera-1.17.jar
jersey-client-1.17.jar
jersey-core-1.17.jar
jersey-guice-1.17.jar
jersey-json-1.17.jar
jersey-multipart-1.17.jar
jersey-server-1.17.jar
jersey-servlet-1.17.jar
jettison-1.1.jar
jsr311-api-1.1.1.jar
validation-api-1.0.0.GA.jar
I got the issue resolved. The issue was that I was importing classes from both versions of Jackson libraries as "Perception" had indicated. I can now use the latest stable version of Jackson libraries with Jersey client.
Thanks Perception for your suggestion.
Here is what my client code now looks like.
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.jaxrs.json.JacksonJsonProvider;
import com.sun.jersey.api.client.Client;
import com.sun.jersey.api.client.WebResource;
import com.sun.jersey.api.client.config.ClientConfig;
import com.sun.jersey.api.client.config.DefaultClientConfig;
import com.sun.jersey.api.json.JSONConfiguration;
...
/**
* Wrapper class for a RESTful Service
*/
public class RestServiceWrapper
{
public ResponseData performRequest(
List<String> reqArgs,
ResponseType rType,
Class<?> dataType
)
{
ResponseData data = new ResponseData();
for(String arg: nullCheck(reqArgs))
{
if(StringUtils.isNotEmpty(arg))
{
webResource=webResource.path(arg);
}
}
data.data = webResource
.accept(MediaType.APPLICATION_JSON) //For now only JSON supported
.get(AssetDataResponse.class);
data.rType = ResponseType.JSON;
return data;
}
protected ServiceInfo svcInfo;
public RestServiceWrapper(ServiceInfo svcInfo) {
ClientConfig clientConfig = new DefaultClientConfig();
clientConfig.getFeatures().put(JSONConfiguration.FEATURE_POJO_MAPPING, Boolean.TRUE);
clientConfig.getClasses().add(JacksonJsonProvider.class);
client = Client.create(clientConfig);
this.svcInfo = svcInfo;
this.webResource =
client.resource(
String.format("http://%s:%d/%s",svcInfo.Host,svcInfo.Port,svcInfo.EndPoint));
}
private static <T> Iterable<T> nullCheck(Iterable<T> iterable) {
return iterable == null ? Collections.<T>emptyList() : iterable;
}
protected Client client;
protected WebResource webResource;
}
I had to include the following line failing which I ran into the original error again
clientConfig.getClasses().add(JacksonJsonProvider.class);
the JacksonJsonProvider imported from
//jackson-jaxrs-json-provider-2.1.3.jar
import com.fasterxml.jackson.jaxrs.json.JacksonJsonProvider;
My jars now look like.
annotations-1.3.9.jar
asm-3.1.jar
codemodel-2.4.1.jar
jackson-annotations-2.1.2.jar
jackson-core-2.1.3.jar
jackson-databind-2.1.3.jar
jackson-jaxrs-json-provider-2.1.3.jar
jcommander-1.30.jar
jersey-apache-client-1.17.jar
jersey-atom-abdera-1.17.jar
jersey-client-1.17.jar
jersey-core-1.17.jar
jersey-guice-1.17.jar
jersey-json-1.17.jar
jersey-multipart-1.17.jar
jersey-server-1.17.jar
jersey-servlet-1.17.jar
jettison-1.1.jar
jsonschema2pojo-core-0.3.5.jar
jsr311-api-1.1.1.jar
validation-api-1.0.0.GA.jar

How to parse input stream using net.sf.json library

Following is the response in Json i am getting after making get request to Http API Format,
[{"name":"test","tracing":false},{"name":"dyn1","tracing":false},
{"name":"dyn2","tracing":false},{"name":"esb","tracing":false}]
Could you please post a sample code to parse this json object to get individual Host object with name and tracing.
Thanks,
Amol
String myDataAsAString = "[{\"name\":\"test\",\"tracing\":false},{\"name\":\"dyn1\",\"tracing\":false},
{\"name\":\"dyn2\",\"tracing\":false},{\"name\":\"esb\",\"tracing\":false}]";
JSONArray hostArray = JSONArray.fromObject(myDataAsAString);
for(int i = 0; i < hostArray.size(); i++)
{
JSONObject hostObject = hostArray.getJSONObject(i);
String hostName = hostObject.getString("name");
boolean tracing = hostObject.getBoolean("tracing");
...your code for each element here
}
You can yse GSON library http://code.google.com/p/google-gson/
Try:
import com.google.gson.Gson;
public class Test {
public static void main(String[] args){
String json = "[{'name':'test','tracing':false},{'name':'dyn1','tracing':false},\n" +
"{'name':'dyn2','tracing':false},{'name':'esb','tracing':false}]";
HostObj[] hostObjects = new Gson().fromJson(json, HostObj[].class);
}
class HostObj {
private String name;
private boolean tracing;
HostObj() {
}
public String getName() {
return name;
}
public void setName(String name) {
name = name;
}
public boolean isTracing() {
return tracing;
}
public void setTracing(boolean tracing) {
tracing = tracing;
}
}
}

Unmarshalling JSON array via Jettison/Resteasy

Ran into a similar problem like the following forum post:
http://jersey.576304.n2.nabble.com/parsing-JSON-with-Arrays-using-Jettison-td5732207.html
Using Resteasy 2.0.1GA with Jettison 1.2 and getting a problem marshalling arrays when involving namespace mappings. See code below. Basically if the number of array entries are greater than one and namespace mappings are used. Anybody else run into this problem? The Nabble form poster got around it by writing a custom unmarshaller.
I either need to isolate the Jettison bug or write a Resteasy extension of the JettisonMappedUnmarshaller class (which hands over the namespace mappings and unmarshaller to the Jettison Configuration).
The following code doesn't unmarshall (post step) if the properties variables contains 2 or more entries.
public class Experimenting {
#Path("test")
public static class MyResource {
#XmlAccessorType(XmlAccessType.FIELD)
#XmlType(name = "Property", propOrder = { "name", "value" })
public static class MyProperty {
#XmlElement(name = "Name", required = true)
protected String name;
#XmlElement(name = "Value", required = true)
protected String value;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getValue() {
return value;
}
public void setValue(String value) {
this.value = value;
}
}
#XmlType(name = "MyElement", propOrder = { "myProperty" })
#XmlAccessorType(XmlAccessType.FIELD)
#XmlRootElement(name = "MyElement", namespace = "http://www.klistret.com/cmdb/ci/commons")
#Mapped(namespaceMap = { #XmlNsMap(namespace = "http://www.klistret.com/cmdb/ci/commons", jsonName = "com.klistret.cmdb.ci.commons") })
public static class MyElement {
#XmlElement(name = "MyProperty", namespace = "http://www.klistret.com/cmdb/ci/commons")
protected List myProperty;
public List getMyProperty() {
if (myProperty == null) {
myProperty = new ArrayList();
}
return this.myProperty;
}
public void setMyProperty(List myProperty) {
this.myProperty = myProperty;
}
}
#GET
#Path("myElement/{id}")
#Produces(MediaType.APPLICATION_JSON)
public MyElement getMy(#PathParam("id")
Long id) {
MyElement myElement = new MyElement();
MyProperty example = new MyProperty();
example.setName("example");
example.setValue("of a property");
MyProperty another = new MyProperty();
another.setName("another");
another.setValue("just a test");
MyProperty[] properties = new MyProperty[] { example, another };
myElement.setMyProperty(Arrays.asList(properties));
return myElement;
}
#POST
#Path("/myElement")
#Consumes(MediaType.APPLICATION_JSON)
#Produces(MediaType.APPLICATION_JSON)
public MyElement createMy(MyElement myElement) {
List properties = myElement.getMyProperty();
System.out.println("Properties size: " + properties.size());
return myElement;
}
}
private Dispatcher dispatcher;
#Before
public void setUp() throws Exception {
// embedded server
dispatcher = MockDispatcherFactory.createDispatcher();
dispatcher.getRegistry().addPerRequestResource(MyResource.class);
}
#Test
public void getAndCreate() throws URISyntaxException,
UnsupportedEncodingException {
MockHttpRequest getRequest = MockHttpRequest.get("/test/element/44");
MockHttpResponse getResponse = new MockHttpResponse();
dispatcher.invoke(getRequest, getResponse);
String getResponseBodyAsString = getResponse.getContentAsString();
System.out.println(String.format(
"Get Response code [%s] with payload [%s]", getResponse
.getStatus(), getResponse.getContentAsString()));
MockHttpRequest postRequest = MockHttpRequest.post("/test/element");
MockHttpResponse postResponse = new MockHttpResponse();
postRequest.contentType(MediaType.APPLICATION_JSON);
postRequest.content(getResponseBodyAsString.getBytes("UTF-8"));
dispatcher.invoke(postRequest, postResponse);
System.out.println(String.format(
"Post Response code [%s] with payload [%s]", postResponse
.getStatus(), postResponse.getContentAsString()));
}
}
Do you have to use Jettison? If not I would recommend just switching to use Jackson instead; this typically solves array/list related problems (problem with Jettison is that it converts to XML model, which makes it very hard to tell arrays from objects -- there are bugs, too, but it is fundamentally hard thing to get working correctly).

Casting an object using 'as' returns null: myObject = newObject as MyObject; // null

I am trying to create a custom object in AS3 to pass information to and from a server, which in this case will be Red5. In the below screenshots you will see that I am able to send a request for an object from as3, and receive it successfully from the java server. However, when I try to cast the received object to my defined objectType using 'as', it takes the value of null. It is my understanding that that when using "as" you're checking to see if your variable is a member of the specified data type. If the variable is not, then null will be returned.
This screenshot illustrates that I am have successfully received my object 'o' from red5 and I am just about to cast it to the (supposedly) identical datatype testObject of LobbyData:
Enlarge
However, when testObject = o as LobbyData; runs, it returns null. :(
Enlarge
Below you will see my specifications both on the java server and the as3 client. I am confident that both objects are identical in every way, but for some reason flash does not think so. I have been pulling my hair out for a long time, does anyone have any thoughts?
AS3 Object:
import flash.utils.IDataInput;
import flash.utils.IDataOutput;
import flash.utils.IExternalizable;
import flash.net.registerClassAlias;
[Bindable]
[RemoteClass(alias = "myLobbyData.LobbyData")]
public class LobbyData implements IExternalizable
{
private var sent:int; // java sentinel
private var u:String; // red5 username
private var sen:int; // another sentinel?
private var ui:int; // fb uid
private var fn:String; // fb name
private var pic:String; // fb pic
private var inb:Boolean; // is in the table?
private var t:int; // table number
private var s:int; // seat number
public function setSent(sent:int):void
{
this.sent = sent;
}
public function getSent():int
{
return sent;
}
public function setU(u:String):void
{
this.u = u;
}
public function getU():String
{
return u;
}
public function setSen(sen:int):void
{
this.sen = sen;
}
public function getSen():int
{
return sen;
}
public function setUi(ui:int):void
{
this.ui = ui;
}
public function getUi():int
{
return ui;
}
public function setFn(fn:String):void
{
this.fn = fn;
}
public function getFn():String
{
return fn;
}
public function setPic(pic:String):void
{
this.pic = pic;
}
public function getPic():String
{
return pic;
}
public function setInb(inb:Boolean):void
{
this.inb = inb;
}
public function getInb():Boolean
{
return inb;
}
public function setT(t:int):void
{
this.t = t;
}
public function getT():int
{
return t;
}
public function setS(s:int):void
{
this.s = s;
}
public function getS():int
{
return s;
}
public function readExternal(input:IDataInput):void
{
sent = input.readInt();
u = input.readUTF();
sen = input.readInt();
ui = input.readInt();
fn = input.readUTF();
pic = input.readUTF();
inb = input.readBoolean();
t = input.readInt();
s = input.readInt();
}
public function writeExternal(output:IDataOutput):void
{
output.writeInt(sent);
output.writeUTF(u);
output.writeInt(sen);
output.writeInt(ui);
output.writeUTF(fn);
output.writeUTF(pic);
output.writeBoolean(inb);
output.writeInt(t);
output.writeInt(s);
}
}
Java Object:
package myLobbyData;
import org.red5.io.amf3.IDataInput;
import org.red5.io.amf3.IDataOutput;
import org.red5.io.amf3.IExternalizable;
public class LobbyData implements IExternalizable
{
private static final long serialVersionUID = 115280920;
private int sent; // java sentinel
private String u; // red5 username
private int sen; // another sentinel?
private int ui; // fb uid
private String fn; // fb name
private String pic; // fb pic
private Boolean inb; // is in the table?
private int t; // table number
private int s; // seat number
public void setSent(int sent)
{
this.sent = sent;
}
public int getSent()
{
return sent;
}
public void setU(String u)
{
this.u = u;
}
public String getU()
{
return u;
}
public void setSen(int sen)
{
this.sen = sen;
}
public int getSen()
{
return sen;
}
public void setUi(int ui)
{
this.ui = ui;
}
public int getUi()
{
return ui;
}
public void setFn(String fn)
{
this.fn = fn;
}
public String getFn()
{
return fn;
}
public void setPic(String pic)
{
this.pic = pic;
}
public String getPic()
{
return pic;
}
public void setInb(Boolean inb)
{
this.inb = inb;
}
public Boolean getInb()
{
return inb;
}
public void setT(int t)
{
this.t = t;
}
public int getT()
{
return t;
}
public void setS(int s)
{
this.s = s;
}
public int getS()
{
return s;
}
#Override
public void readExternal(IDataInput input)
{
sent = input.readInt();
u = input.readUTF();
sen = input.readInt();
ui = input.readInt();
fn = input.readUTF();
pic = input.readUTF();
inb = input.readBoolean();
t = input.readInt();
s = input.readInt();
}
#Override
public void writeExternal(IDataOutput output)
{
output.writeInt(sent);
output.writeUTF(u);
output.writeInt(sen);
output.writeInt(ui);
output.writeUTF(fn);
output.writeUTF(pic);
output.writeBoolean(inb);
output.writeInt(t);
output.writeInt(s);
}
}
AS3 Client:
public function refreshRoom(event:Event)
{
var resp:Responder=new Responder(handleResp,null);
ncLobby.call("getLobbyData", resp, null);
}
public function handleResp(o:Object):void
{
var testObject:LobbyData=new LobbyData;
testObject = o as LobbyData;
trace(testObject);
}
Java Client
public LobbyData getLobbyData(String param)
{
LobbyData lobbyData1 = new LobbyData();
lobbyData1.setSent(5);
lobbyData1.setU("lawlcats");
lobbyData1.setSen(5);
lobbyData1.setUi(5);
lobbyData1.setFn("lulz");
lobbyData1.setPic("lulzagain");
lobbyData1.setInb(true);
lobbyData1.setT(5);
lobbyData1.setS(5);
return lobbyData1;
}
As you already figured out, you should use registerClassAlias as the RemoteClass works out of the box only for Flex projects (as bindable, etc).
Be sure to call registerClassAlias before any serializing / deserializing occurs.
Also, the debugger is showing you the actual tipe of your "o" parameter, which is object. This shows that the player is not correctly mapping the AMF serialized object's class to any of your classes (so, by default, it goes with Object). You should see a LobbyData object in the debugger; otherwise, no matter how you cast / coerce it, it won't work.
The objet needs to be declared before the responder is called.
public function refreshRoom(event:Event)
{
var testObject:LobbyData=new LobbyData;
var resp:Responder=new Responder(handleResp,null);
ncLobby.call("getLobbyData", resp, null);
}
public function handleResp(o:Object):void
{
testObject = o as LobbyData;
trace(testObject);
}
Actually if you want to workaround the type casting you can simply add this to your constructor:
public function dataAwareObject(o:* = null)
{
//TODO: implement function
super();
if(o){
for(var a:* in o)
this[a] = o[a];
}
}
}
Works like a charm.