BlazeDS - AMFConnection.call giving HTTP 400 status - java

I'm trying to use BlazeDS's AMFConnection class to connect to pyamf, but when I call AMFConnection.call(), I get HTTP status 400 (Bad Request - "The request body was unable to be successfully decoded."). I'm more or less following this example: (pyamf.org/wiki/ClientHowTo ... sorry, I'm a new user so I guess I can't use hyperlinks. append a "http://" to those if you want to follow them)
Here's my code:
package amfconnectiontest;
import flex.messaging.io.amf.client.AMFConnection;
import flex.messaging.io.amf.client.exceptions.*;
public class Main {
public static void main(String[] args) {
AMFConnection amfConnection = new AMFConnection();
String url = "http://demo.pyamf.org/gateway/recordset";
String service = "service.getLanguages";
try
{
amfConnection.connect(url);
}
catch (ClientStatusException cse)
{
System.out.println(cse);
return;
}
// Make a remoting call and retrieve the result.
try
{
Object result = amfConnection.call(service);
System.out.println("results: " + result.toString());
}
catch (ClientStatusException cse)
{
System.out.println(cse);
}
catch (ServerStatusException sse)
{
System.out.println(sse);
}
// Close the connection.
amfConnection.close();
}
}
Any ideas?

The ability to en/decode BlazeDS specific messages (implementing ISmallMessage) has landed on the PyAMF trunk (r2726 and up). See the related ticket - http://pyamf.org/ticket/581
This version or one very similar is likely to become 0.5. If you need to connect to a BlazeDS service I would suggest checking out the trunk.

Related

Get UnirestConfigException when using Unirest API in Java

Getting Unirest Config exception when I use java with Unirest API to call the web service asynchronous way. It is working as expected in the sync method.
I am writing a Java code for Apache Spark to call REST API.
Future> future = ui.post("http://x.x.x.x:x/xwa/evalrules").body(Str).asStringAsync(
new Callback() {
public void failed(UnirestException e) {
System.out.println("JTX Failed Get message"+ e.getMessage());
}
public void completed(HttpResponse<String> resp) {
System.out.println(new Date() + " Consumer JTXX recvd response -> " + resp.getStatus() + "/" + resp.getBody());
//out_JSON=resp.body();
}
public void cancelled() {
System.out.println("The request has been cancelled JTX");
}
});
Expected: It is working as expected for first few calls. post that it is failing. I suspected the timeout so i have already disabled using approach.
Config c = Unirest.config().socketTimeout(0).connectTimeout(0).concurrency(10, 8);
UnirestInstance ui = new UnirestInstance(c);
Error Message:
kong.unirest.UnirestConfigException: Http Clients are already built in order to build a new config execute Unirest.config().reset() before changing settings.
This should be done rarely.
Any suggestions on how to resolve this will be highly appreciated. Thanks.
Muthu

How to parse DFT_P03 message with ZPM segment

I am coding a server application that will receive DFT_P03 messages with an added ZPM segment (which i have created a class for as per the HAPI documentation). Currently i am able to access this field as a generic segment when doing the following :
#Override
public Message processMessage(Message t, Map map) throws ReceivingApplicationException, HL7Exception
{
String encodedMessage = new DefaultHapiContext().getPipeParser().encode(t);
logEntryService.logDebug(LogEntry.CONNECTIVITY, "Received message:\n" + encodedMessage + "\n\n");
try
{
InboundMessage inboundMessage = new InboundMessage();
inboundMessage.setMessageTime(new Date());
inboundMessage.setMessageType("Usage");
DFT_P03 usageMessage = (DFT_P03) t;
Segment ZPMSegment = (Segment)usageMessage.get("ZPM");
inboundMessage.setMessage(usageMessage.toString());
Facility facility = facilityService.findByCode(usageMessage.getMSH().getReceivingFacility().getNamespaceID().getValue());
inboundMessage.setTargetFacility(facility);
String controlID = usageMessage.getMSH().getMessageControlID().encode();
controlID = controlID.substring(controlID.indexOf("^") + 1, controlID.length());
inboundMessage.setControlId(controlID);
Message response;
try
{
inboundMessageService.save(inboundMessage);
response = t.generateACK();
logEntryService.logDebug(LogEntry.CONNECTIVITY, "Message ACKed");
}
catch (Exception ex)
{
response = t.generateACK(AcknowledgmentCode.AE, new HL7Exception(ex));
logEntryService.logDebug(LogEntry.CONNECTIVITY, "Message NACKed");
}
return response;
}
catch (IOException e)
{
logEntryService.logDebug(LogEntry.CONNECTIVITY, "Message rejected");
throw new HL7Exception(e);
}
}
I have created a DFT_P03_Custom class as following :
public class DFT_P03_Custom extends DFT_P03
{
public DFT_P03_Custom() throws HL7Exception
{
this(new DefaultModelClassFactory());
}
public DFT_P03_Custom(ModelClassFactory factory) throws HL7Exception
{
super(factory);
String[] segmentNames = getNames();
int indexOfPid = Arrays.asList(segmentNames).indexOf("FT1");
int index = indexOfPid + 1;
Class<ZPM> type = ZPM.class;
boolean required = true;
boolean repeating = false;
this.add(type, required, repeating, index);
}
public ZPM getZPM()
{
return getTyped("ZPM", ZPM.class);
}
}
When trying to typecast the message to a DFT_P03_Custom instance i get a ClassCastException. As per their documentation, i did create the CustomModelClassFactory class but using this i just get tons of validation errors on the controlId field.
I am already using an identical logic to send custom MFN_M01 messages with an added ZFX segment and that works flawlessly. I understand there is some automatic typecasting being done by HAPI when it receives a DFT_P03 message and that is likely what i need to somehow override for it to be able to give me a DFT_P03_Custom instance instead.
If you have some insight on how i can achieve this without having to use a generic segment instance please help!
Thank you!
I finally figured this out. The only way i got this to work was to generate a conformance profile XML file (using an example message from our application as a base) with the messaging workbench on the HAPI site and use the maven plugin to generate the message and segment classes. Only with these classes am i able to correctly parse a message to my custom class. One thing to note is that it DOES NOT work if i try to use the MSH, PID, PV1 or FT1 classes provided by HAPI and use my Z-segment class. It only works if all the segments are the classes generated by the conformance plugin. This combined with a CustomModelClassFactory class (as shown on the HAPI website) and the proper package structure finally allowed me to access my Z-segment.

How to set various parameters for Java RMI based communication?

While performing a client-server communication with various forums, I am unable to perform Remote-object's lookup on the client machine.
The errors which I receive are ConnectIOException(NoRouteToHostException), and sometimes ConnectException and sometimes someother.
This is not what I want to ask. But, the main concern is how should I setup client platform and server platform --- talking about networking details --- this is what I doubt interferes with my connection.
My questions :-
How should I edit my /etc/hosts file on both client-side and server-side? Server's IP- 192.168.1.8 & Client's IP-192.168.1.100. Means, should I add the system name in both the files:
192.168.1.8 SERVER-1 # on the server side
192.168.1.100 CLIENT-1 # on the client side
Should I edit like this? Can this be one of the possible concerns? I just want to remove any doubts left over to perform the rmi-communication!
Also, I am also setting Server's hostname property using System.setProperty("java.rmi.server.hostname",192.168.1.8); on the server side. Should I do the same on the client-side too?
I've read about setting classpath while running the java program on both server-side as well as the client-side. I did this too,but,again the same exceptions. No difference at all. I've read that since Java update 6u45, classpaths aren't necessary to include! Please throw some light on this too...
If I am missing something, Please enlighten about the same too. A brief idea/link to resources are most preferred.
You don't need any of this unless you have a problem. The most usual problem is the one described in the RMI FAQ #A.1, and editing the hosts file of the server or setting java.rmi.server.hostname in the server JVM is the solution to that.
'No route to host' is a network connectivity problem, not an RMI problem, and not one you'll solve with code or system property settings.
Setting the classpath has nothing to do with network problems.
Here is server example of which transfers an concrete class. This class must be exist in server and client classpath with same structure
Message:
public class MyMessage implements Serializable {
private static final long serialVersionUID = -696658756914311143L;
public String Title;
public String Body;
public MyMessage(String strTitle) {
Title = strTitle;
Body = "";
}
public MyMessage() {
Title = "";
Body = "";
}
}
And here is the server code that gets an message and returns another message:
public class SimpleServer {
public String ServerName;
ServerRemoteObject mRemoteObject;
public SimpleServer(String pServerName) {
ServerName = pServerName;
}
public void bindYourself() {
try {
mRemoteObject = new ServerRemoteObject(this);
java.rmi.registry.Registry iRegistry = LocateRegistry.getRegistry(RegistryContstants.RMIPort);
iRegistry.rebind(RegistryContstants.CMName, mRemoteObject);
} catch (Exception e) {
e.printStackTrace();
mRemoteObject = null;
}
}
public MyMessage handleEvent(MyMessage mMessage) {
MyMessage iMessage = new MyMessage();
iMessage.Body = "Response body";
iMessage.Title = "Response title";
return iMessage;
}
public static void main(String[] server) {
SimpleServer iServer = new SimpleServer("SERVER1");
iServer.bindYourself();
while (true) {
try {
Thread.sleep(10000);
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
and here is the remote interface of server remote object:
public interface ISimpleServer extends java.rmi.Remote{
public MyMessage doaction(MyMessage message) throws java.rmi.RemoteException;
}
all you need is adding MyMessage class both in server and client classpath.

Check client is alive with HttpServletRequest object

I'm writing a Spring web application and I'm mapping the "/do" URL path to the following Controller's method
#Controller
public class MyController
{
#RequestMapping(value="/do", method=RequestMethod.GET)
public String do()
{
File f = new File("otherMethodEnded.tmp");
while (!f.exists())
{
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
}
}
// ok, let's continue
}
}
The otherMethodEnded.tmp file is written by one another Controller's method, so when the client calls the second URL I expect the first method to exit the while loop.
Everything works, except when the client calls the "/do" URL and then closes the connection before the response was received. The problem is that the server remains in the while (!f.exists()) loop even though the client is down and cannot call the second URL to unlock the while loop.
I would try to retrieve the connection status of the "/do" URL and exit the loop when the connection is closed by the client, but I cannot find any way to do so.
I tried with the HttpServletRequest.getSession(false) method but the returned HttpSession object is always not null, so the HttpServletRequest object is not updated in case of connection close of the client.
How can I check whether the client is still waiting for the risponse or not?
The simplest way to verify something is not right is to define a timeout value and then during your loop test if your time spent waiting has exceeded the timeout.
something like:
#Controller
public class MyController
{
private static final long MAX_LOOP_TIME = 1000 * 60 * 5; // 5 minutes? choose a value
#RequestMapping(value="/do", method=RequestMethod.GET)
public String do()
{
File f = new File("otherMethodEnded.tmp");
long startedAt = System.currentTimeMillis()
boolean forcedExit = false;
while (!forcedExit && !f.exists())
{
try {
Thread.sleep(5000);
if (System.currentTimeMillis() - startedAt > MAX_LOOP_TIME) {
forcedExit = true;
}
} catch (InterruptedException e) {
forcedExit = true;
}
}
// ok, let's continue
// if forcedExit , handle error scenario?
}
}
Additionally: InterruptedException is not something to blindly catch and ignore. see this discussion
In your case I would really exit the while loop if you're interrupted.
You only know if the client is no longer waiting on your connection when you notice the output stream you write to (response.outputstream) is closed. But there isn't a way to detect it.
(see this question for details)
Seeing as you've indicated your client does occasional callbacks, you could on the clientside poll if the other call has been completed. If this other call has completed, do the operation, otherwise return directly and have the client do the call again. (assuming you are sending json, but adapt as you require)
something like
public class MyController
{
#RequestMapping(value="/do", method=RequestMethod.GET)
public String do()
{
File f = new File("otherMethodEnded.tmp");
if (f.exists()) {
// do what you set out to do
// ok, let's continue
// and return with a response that indicates the call did what it did
// view that returns json { "result" : "success" }
return "viewThatSIgnalsToClientThatOperationSucceeded";
} else {
// view that returns json: { "result" : "retry" }
return "viewThatSignalsToClientToRetryIn5Seconds";
}
}
}
Then the clientside would run something like: (pseudojavascript as it's been a while)
val callinterval = setInterval(function() { checkServer() }, 5000);
function checkServer() {
$.ajax({
// ...
success: successFunction
});
}
function successFunction(response) {
// connection succeeded
var json = $.parseJSON(response);
if (json.result === "retry") {
// interval will call this again
} else {
clearInterval(callinterval);
if (json.result === "success") {
// do the good stuff
} else if (json.result === "failure") {
// report that the server reported an error
}
}
}
Ofcourse this is just semi-serious code but it's roughly how i'd try it if I were to have the dependency. If this is regarding afile upload, keep in mind that this file may not contain all of the bytes yet. file exists != file = completely uploaded, unless you use move it. cp / scp / etc. is not atomic.

RESTEasy JSON Exception Response: Send list of objects

I have web client (HTML5) and backend server based on RESTEasy webservices and session beans. In my server side code I am iterating over list of objects and per object i am executing some business logic:
List<TestTO> failedTestList = new ArrayList<TestTO>();
for (TestTO testTO : testTOList) {
try {
// some weired business logic :P
} catch (Exception e) {
logger.error("Unable to create data -" + e.getMessage());
failedTestList.add(testTO);
}
}
if (!failedTestList.isEmpty()) {
// throw custom exception embedded with failed TO list
}
I have written custome exception handlers, to catch exceptions and return proper response back to client. This class looks like:
public class CustomExceptionHandler implements ExceptionMapper<CustomException> {
public CustomException getCustomErrorCode(final CustomException customException) {
// Some logic to get cause and set error code
return customException;
}
#Override
public Response toResponse(final CustomException customException) {
return Response.serverError().entity(
"{\"Error Code\":\"" + getCustomErrorCode(customException).getErrorCode() + "\", "
+ "\"Error Message\":\"" + customException.getLocalizedMessage() + "\"}").build();
}
}
I am thinking of an option to send this failed TO list back to client, so that it can understand processing of which objects got failed. I was going through different articles, but could not find anything which fits my requirement.
Please give me an idea and link to reference, on how to implement such requirement. Please note that, my client expects response in JSON format. Please let me know, if you require more information.
Thanks.

Categories

Resources