I've been struggling with this problem for last few hours but still got no idea what's wrong. Here's the scenario:
Application built on top of the Mate framework sometimes need to exchange data with remote server over plain binary socket.
When specific packet is received I have to switch view (using ViewStack) and create custom panel (using PopUpManager class). This custom panel contains a dataGrid component which has to be populated with some XML received along with mentioned packet.
Trouble is that when I try to assign XML to DataGrid's dataProvider I constantly get "Cannot access a property or method of a null object reference" error. The only thing I can think of is some kind of race when processing events and creating components.
Here are the most interesting pieces of code:
<!-- LoginEvent.LOGIN_OK _____________________________________________________________________ -->
<EventHandlers type="{LoginEvent.LOGIN_OK}">
<MethodInvoker generator="{UserManager}" method="storeCurrentUser" arguments="{event.fullName}"/>
<EventAnnouncer generator="{NavigationEvent}" type="{NavigationEvent.MAIN}"/>
<MethodInvoker generator="{CustomSocket}" method="listBoards"/>
In the above code I react when the LOGIN_OK packet is received.
Store user's data, change the view and ask the Socket class wrapper to send request (the reponse for that request is our verySpecificPacket)
Here's detailed info about how I change the view and create custom pop up. In MainUI.mxml:
<mate:Listener type="{NavigationEvent.MAIN}" method="handleNavigationEvent" />
private function launchBoardListWindow():void {
Logger.info("launchBoardListWindow()");
var win:BoardList = PopUpManager.createPopUp(this, BoardList, true) as BoardList;
PopUpManager.centerPopUp(win);
}
private function handleNavigationEvent(event:NavigationEvent):void {
viewStack.selectedIndex = MAIN;
launchBoardListWindow();
}
The third position in EventMap isn't important, it just ask socket wrapper to send some kind of packet. The server is supposed to respond with verySpecialPacket along with XML payload. And here we are at the part where the error is. In mxml describing my custom panel I set up a listener for an event which is being dispatched after my verySpecialPacket is received.
public function handleListBoardsEvent(e:ListBoardsEvent):void {
Logger.info("handleListBoardsEvent");
xmlData = e.xml;
boardList.dataProvider = xmlData.children(); // Here's the error!!!
}
I really don't get it, since the xmlData is OK, and custom panel with all child components were created. Thanks for reading!
You're likely on the right track in respect of a race condition.
Suggestion:
Put a try { ... } catch (e:Error) { trace("error"); } block around the code in your handleListBoardsEvent() method.
Then, put a breakpoint on the trace() and, when it hits, take a good look around at the various objects involved.
My guess is that you're attempting to access the boardList object before it is created - i.e. it's null.
The other possibility is that boardList.dataProvider is a setter and there's code in the setter that's barfing. (Although, if that were the case, I'm sure you would have noticed the stacktrace inFlexBuilder)
Related
I have a requirement where I will be receiving a batch of records. I have to disassemble and insert the data into DB which I have completed. But I don't want any message to come out of the pipeline except the last custom made message.
I have extended FFDasm and called Disassembler(), then we have GetNext() which is returning every debatched message out and they are failing as there is subscribers. I want to send nothing out from GetNext() until Last message.
Please help if anyone have already implemented this requirement. Thanks!
If you want to send only one message on the GetNext, you have to call on Disassemble method to the base Disassemble and get all the messages (you can enqueue this messages to manage them on GetNext) as:
public new void Disassemble(IPipelineContext pContext, IBaseMessage pInMsg)
{
try
{
base.Disassemble(pContext, pInMsg);
IBaseMessage message = base.GetNext(pContext);
while (message != null)
{
// Only store one message
if (this.messagesCount == 0)
{
// _message is a Queue<IBaseMessage>
this._messages.Enqueue(message);
this.messagesCount++;
}
message = base.GetNext(pContext);
}
}
catch (Exception ex)
{
// Manage errors
}
Then on GetNext method, you have the queue and you can return whatever you want:
public new IBaseMessage GetNext(IPipelineContext pContext)
{
return _messages.Dequeue();
}
The recommended approach is to publish messages after disassemble stage to BizTalk message box db and use a db adapter to insert into database. Publishing messages to message box and using adapter will provide you more options on design/performance and will decouple your DB insert from receive logic. Also in future if you want to reuse the same message for something else, you would be able to do so.
Even then for any reason if you have to insert from pipeline component then do the following:
Please note, GetNext() method of IDisassembler interface is not invoked until Disassemble() method is complete. Based on this, you can use following approach assuming you have encapsulated FFDASM within your own custom component:
Insert all disassembled messages in disassemble method itself and enqueue only the last message to a Queue class variable. In GetNext() message then return the Dequeued message, when Queue is empty return null. You can optimize the DB insert by inserting multiple rows at a time and saving them in batches depending on volume. Please note this approach may encounter performance issues depending on the size of file and number of rows being inserted into db.
I am calling DBInsert SP from GetNext()
Oh...so...sorry to say, but you're doing it wrong and actually creating a bunch of problems doing this. :(
This is a very basic scenario to cover with BizTalk Server. All you need is:
A Pipeline Component to Promote BTS.InterchageID
A Sequential Convoy Orchestration Correlating on BTS.InterchangeID and using Ordered Delivery.
In the Orchestration, call the SP, transform to SOAP, call the SOAP endpoint, whatever you need.
As you process the Messages, check for BTS.LastInterchagneMessage, then perform your close out logic.
To be 100% clear, there are no practical 'performance' issues here. By guessing about 'performance' you've actually created the problem you were thinking to solve, and created a bunch of support issues for later on, sorry again. :( There is no reason to not use an Orchestration.
As noted, 25K records isn't a lot. Be sure to have the Receive Location and Orchestration in different Hosts.
I'm writing part of a cross-platform application, where we mostly use REST (jersey) and Hibernate to communicate between systems. I'm new to JavaFX, but my side of the program should use it to get input values from users. Here is how the code flow would look:
public class startingClass{
...
public void startingMethod(Payload payload){
//send REST requests to different places with different payloads, like:
Response response = Utility.sendPostRequest(URI, payload2);
something = response.readEntity(something.class)
//more processing with the returned values
...
}}
In one of the places where I sent a request:
#Path("something")
#Consumes(MediaType.APPLICATION_JSON)
#Produces(MediaType.APPLICATION_JSON + ";charset=UTF-8")
public class Resource{
...
#POST
#Path(something)
public Response doSomething(Payload payload) {
//show JavaFX window with text fields and an okay button
JavaFXClass.launch(JavaFXClass.class);
/* THIS IS WHERE I would need to get back the input values somehow */
//payload3 has the input values I need to send back
return Response.entity(payload3).build();
}}
The JavaFX class extends application and and overrides the (void) start method where I put together the window I want to show and after the button click (if inputs are okay) I close the window.
So the idea is that the startingMethod would have to wait, until the response comes back (maybe return with some default values, if the user doesnt type in anything for a minute - what would be the elegant solution for that?) with the input values. This would guarantee the sync.
If I use more REST or database saves inside the JavaFX class then I can't be sure the values are there by the time I wanna use them in the startingMethod (probably not) and it's probably a really bad looking solution anyway.
What could I do? I dont know much about callback methods in javafx, can those help me here? Thanks!
In the end I moved the JavaFXClass into the Resource class. Meaning Resource class extends Application, overrides start, etc. In the doSomethingMethod I call launch in a try-catch block, catch the IllegalStateException if needed and call start() instead (also in a try-catch block). The textfield input values are stored in a global variable after.
Also in the start() method I havePlatform.setImplicitExit(false);
so the doSomethingMethod() can be called multiple times without a problem, starting the javaFX window. It's not a pretty solution.
I am currently stuck and cant find any answers anywhere!! So any help at all would be great!
Currently Im trying to create a sharedObject on a client and send a string from the client containing information based on phone hardware(e.g. accelerometer and geolocation) to ams. From here I want to be able to access information from the sharedObject on the server in the main.asc to use elsewhere!
This is where the problem is occurring I cant access the shared object sent by the client. I sent my shared object like this:
//It's a best practice to always check for a successful NetConnection
protected function onNetStatus(event:NetStatusEvent):void
{
switch(event.info.code)//Check for a successful NetConnection
{
case "NetConnection.Connect.Success"://If the netConnection is a success#
so = SharedObject.getRemote("Data", nc.uri, false);//
so.connect(nc);//connect the sharedObject to the srever
so.addEventListener(SyncEvent.SYNC, syncHandler);//The sync listener
publishCamera(); //Publish the video
case "NetStream.Publish.Start"://If the netStream is a success
//etc
}
}
//It's a best practice to always check for a successful NetConnection
protected function syncHandler(event:SyncEvent):void
{
so.setProperty("username", nameForData);
so.setProperty("age", 21);
so.setProperty("nationality", "irish");
trace("Local"+so.data.username);
Im just not sure how to access so from server side!! I know this works as I have tested it but if there are better ways to implement it I would be glad to get advice!Below is proof that it is hitting the server
Update
Still stuck so I am adding a bounty and updating where I am and how I have progressed!
I have the information hitting the server(sometimes its not constant I dont know why)
Example is sometimes I get this in the admin console most times i have no information in the properties tab
What I am trying to do is to get the file to save every time I flush() the shared object so I can use it elsewhere
My server code is straight from the adobe api this is how it looks in the main asc:
in my onAppStart() I added these lines at the end:
application.allowDebug = true;
application.clearOnAppStop = false;
var Shared = SharedObject.get("Data", true);
trace("Name: "+Shared.name);
trace("Username: "+Shared.getProperty("username"));
in my onAppStop() I added these lines at the end:
var Shared = SharedObject.get("Data", true);
Shared.clear();
The serverside code for shared objects is (almost) the same as the client side.
So using so.getProperty(propertyName) should do the job.
If not check the server side shared object reference from adobe. Maybe that helps.
Hope i didn't missunderstand your question.
I am using Flex and Actionscript 3, along with Webservices, rpc and a callResponder. I want to be able to, for example, say:
loadData1(); // Loads webservice data 1
loadData2(); // Loads webservice data 2
loadData3(); // Loads webservice data 3
However, Actionscript 3 works with async events, so for every call you need to wait for the ResultEvent to trigger when it is done. So, I might want to do the next request every time an event is done. However, I am afraid that threading issues might arise, and some events might not happen at all. I don't think I'm doing a good job of explaining, so I will try to show some code:
private var service:Service1;
var cp:CallResponder = new CallResponder();
public function Webservice()
{
cp.addEventListener(ResultEvent.RESULT, webcalldone);
service = new Service1();
}
public function doWebserviceCall()
{
// Check if already doing call, otherwise do this:
cp.token = service.WebserviceTest_1("test");
}
protected function webcalldone(event:ResultEvent):void
{
// Get the result
var result:String = cp.lastResult as String;
// Check if other calls need to be done, do those
}
Now, I could ofcourse save the actions in an arraylist, but whose to say that the addToArrayList and the check if other calls are available do not mess eachother up, or just miss each other, thereby halting execution? Is there something like a volatile Arraylist? Or is there a completely different, but better solution for this problem?
Use an AsyncToken to keep track of which call the returned data was for http://flexdiary.blogspot.com/2008/11/more-thoughts-on-remoting.html
When I want to store data in an async manor I put it in an array and make a function that will "pop" the element as I send it off.
This function will be called on complete and on error events.
Yes I know there could be an issue with the server and data lost but oh well. That can also be handled
Events will always fire however, it may not be a complete event that gets fired but could be an error event.
Once the array is empty the function is done.
I'm using mx.rpc.http.HTTPService to retrieve data from a web service. On the initial call to "loadWsData", HTTPservice accurately retrieves all the data.
However, on any and all subsequent calls HTTPService does not accurately retrieve the data; rather it always retrieves the first data set. I've confirmed that the web service is providing accurate data, both from web browsers and a ruby ws client script.
My code is below; any ideas on what could be the problem?
private function loadWsData(id:int):void
{
var webService:HTTPService = new HTTPService();
webService.url = "http://xxx.xxx.xxx.xxx:8080/profile/ + id;
webService.method = "GET";
webService.addEventListener(ResultEvent.RESULT, function(event:ResultEvent):void
{
var rawData:String = String(event.result);
var user:Object = JSON.decode(rawData).user; // User object always reflects the first data set retrieved.
....
....
});
webService.send();
}
Not sure what the issue might be, but I have a few suggestions on where to look.
First, there appears to be a bug in your code; the webService.url line is missing a quote mark. That could be messing up the URL you think you are sending. Odd, though, because I don't think what you have shown would compile, so I suspect this is just a cut-and-paste error when you posted this to StackOverflow, but I would trace out that URL just to be sure.
Also, I don't see code to remove the event listener (although it could be in the code you have abbreviated with ellipsis). Is it possible that there are lingering event listeners that are firing in addition to the ones you expect? If the original event listener fires, it will fire with the original data.
Another suggestion: instead of using a closure, try pulling it out to a separate function. That shouldn't be the issue, but maybe scope is playing a role here.
You could try to POST your results.
You might also add an event listener for FAULT, and see if there are any errors being thrown by your service request.