Thank you for your assistance.
Question:
Why does my REST service seem to perform so poorly using rest interfaces in dlang vibe.d when compared to creating request handlers manually?
More Information:
I have been prototyping a RESTful service using the vibe.d library in dlang. I'm running a test where a client sends GET and POST requests to the server with a payload of some given size, say 2048 byte (i.e. the GET response would have 2k, the POST request would have 2k).
I'm using the "registerRestInterface" and "RestInterfaceClient" API in the vibe.d library to create my server and client sort of like this...
Server:
auto routes = new URLRouter;
registerRestInterface(routes, new ArtifactArchive());
auto settings = new HTTPServerSettings();
settings.port = port;
settings.bindAddresses = [host];
settings.options |= HTTPServerOption.distribute;
listenHTTP(settings, routes);
runEventLoop();
Client:
IArtifactArchive archive = new RestInterfaceClient!IArtifactArchive(endpoint)
IArtifactArchive.Payload result;
result = archive.getContents(info.FileDescriptor, offset, info.BlockSize);
I'm not doing anything fancy in my interface. Just filling a byte array and passing it along. I know performance depends on many different things; however I seem to see about 160kB transfer rate when using REST interfaces in vibe.d and roughly 5MB transfer rate when using manual http request handlers like this:
void ManualHandleRequest(HTTPServerRequest req, HTTPServerResponse res) ...
listenHTTP(settings, &ManualHandleRequest);
I really like the REST interface API, but I can't suffer that kind of performance loss in order to use it. Any thoughts on why it seems so much slower than the other method? Perhaps I'm configuring something wrong or missing something. I am somewhat new to the D programming language and the vibe.d library.
Thank you for your time!
I suspect that with custom request handler you actually write response as a byte array. REST interface generator serializes all return data into JSON by default which creates huge overhead compared to raw array.
This is just a random guess though, I need to see actual REST method implementation to say for sure and/or propose solution.
I'm looking for a better way to structure my rest client/rest api code. Currently, I have my rest api with routes like:
get /book
The literal string "/book" is defined on the server side, and on the client side, I have to use the same literal string exactly.
What I would like to do is, have a file serverside which has all of my routes in it, and send it to the client as json, which the client uses for routing.
The basic workflow would be:
Start the server
When the client connects, make a get request for the routes object
return an object like this:
{
getBook:"/book",
createBook:"/book/create"
}
that way my client can use the object returned for the routes instead of hard coding them.
Is this a good idea?
Are there any resources / libraries I should look into if trying to implement client and server side components for a SOAP web service in Java (defined in WSDL) but not wishing to use the WSDL/JAXB-based code generation for client and server stubs?
For the record, the reason I am trying to eschew wsimport for stub generation is that both wsimport and xjc fail to properly generate Java code for the schema files I have to use - which are numerous and rather complex - and despite using episodic compilation I still hit what may likely be bugs in JAXB code generation logic (e.g. see here and here) and overall I have the impression that this technology is not very solid, when it comes to complex schemas.
So, are there any resources or libraries I should look into to help be build SOAP services by writing and reading XML content directly on the HTTP connection? Currently I am just calling write on a java.net.URLConnection like:
URLConnection connection = url.openConnection();
connection.setDoOutput(true); // Triggers POST.
connection.setRequestProperty("Accept" , "text/xml, multipart/related");
connection.setRequestProperty("Content-Type" , "text/xml; charset=utf-8");
connection.setRequestProperty("Host" , url.getHost());
connection.setRequestProperty("Proxy-Connection", "keep-alive");
connection.setRequestProperty("Content-Length" , String.valueOf(postContent.length()));
OutputStream output = connection.getOutputStream();
output.write(postContent.getBytes("UTF-8"));
If you need something "low level" (but not as extreme as writing the messages as strings) have a look at SAAJ.
Reference implementation is here and you can find a starting tutorial in The Java EE 5 Tutorial.
I'm using GWT RPC Calls for Server Side Request so far and it's pretty good. I'm planning on separating my Code into Servlets and GWT Client Side. Since i'm using RPC calls, it seems impossible. The Reason i want to do like this is , i'm planning to provide white labeling option for my App. So if i could separate the code to client code and servlets, i can simply provide the White Labeled client code to my Partners to host on their server. I have checked with GWT RequestBuilder and Access-Control Allow-Origin : Origin from Client Header and it works fine.
However i need to implement gwt-serialization over RequestBuilder request and Servlet Responses. How can i do this ..?
Scenario I like to make:
RequestBuilder sending Serializable String(Which is a IsSerialiazible object) to Servlet.
Servlet deserializes the String to Java Object,Processes and Returns the String Response of a 'IsSerialiazable' Object.
The Response String recieved in GWT RequestBuilder deserialzes it back to a Java Object(JS after Compiling).
I have checked on RemoteServiceServlet class which seems to have some info on serializing and deserializing request and response. But i couldn't get it right to get it to work with RequestBuilder. Any ideas , Hope it will be helpful for everyone.
public final void processPost(HttpServletRequest request,HttpServletResponse response)
throws IOException, ServletException,SerializationException
{
// Read the request fully.
//
String requestPayload = readContent(request);
// Let subclasses see the serialized request.
//
onBeforeRequestDeserialized(requestPayload);
// Invoke the core dispatching logic, which returns the serialized
// result.
//
String responsePayload = processCall(requestPayload);
// Let subclasses see the serialized response.
//
onAfterResponseSerialized(responsePayload);
// Write the response.
//
writeResponse(request, response, responsePayload);
}
GWT RPC and RequestBuilder serve different purposes. We cannot mix/match them.
GWT RPC - Services which fetch Data
GWT Request Builder - fire requests for static resources like js,css, json objects, querying soap services etc
The only feasible solution at the top of my mind for your approach of servicing requests is by using JSON - https://developers.google.com/web-toolkit/doc/latest/tutorial/JSON
You can keep your servlets code as is and then use RequestBuilder to query URL mapped to these servlets for JSON objects. Process the JSON objects using JSNI or Overlay concepts.
I'm trying to get the GWT Serialization & Deserialization source.Unfortunately, i have been stuck with other works and couldn't look on this right now. When i get the GWT Serialization Classes , i will update.
For a web service call using a WSDL, I'm getting the error Cannot find dispatch method for {http://ws.somecompany.com/services}ValidateUser, what does that mean exactly? Does it mean that it cannot find ValidateUser?
This typically means that the SOAP framework could not find the operation that should be invoked via this request. A SOAP framework typically inspects the message to find pointers about how to route the message to the operation. Reasons for this error are mostly configuration issues (different namespaces, different encodings (RPC vs. doc/lit), usage of WS-Addressing vs. plain SOAP etc.)
I had a similar problem and struggling, googling for 1 day. But it was a simple mistake that instead of:
{http://ws.somecompany.com/services}ValidateUser
It should be
{http://ws.somecompany.com/services/}ValidateUser
I had not checked my WSDL clearly.
In my case I solved by making sure that my config file either app.config or web.config depending on your client has correct endpoint. I had wrong address in my endpoint. I changed it and it worked fine.
I also lost a day to this issue, albeit with a different root cause.
In our case, two similar endpoint urls had got mixed up in the properties file. Both services were present and running, but the WSDLs didn't match up, so instead of a ConnectionException, we were getting this SOAPFaultException: "Cannot find dispatch method".
My fifty cent, I got same error message but my case was yet different from all above, so hopefuly it might help someone.
I had .wsdl file, which got outdated without my knowledge when colleagues on the other side of ws renamed some element. Unfortunately, change was not visible when I compared .wsdl with theirs because .wsdl file had .xsd import which actually contained renamed element. After I found change, I updated my .xsd file and tada! error is gone and it worked.
In my case, the following exception was throwing even I've supplied all the parameters
SoapFault exception: [S:Client] Cannot find dispatch method for {}parameters in
After banging my head few hours, just adding a \ while initializing SoapClient solved the problem.
From:
$client = new SoapClient($soapURL);
To:
$client = new \SoapClient($soapURL);
I had the same issue in my .NET Application, In my case setting url same as "http://x-xxx-xx-xx-01:8080//TestProject/testproject?wsdl" (dummy url) solved the problem in the below code.
Vb.Net
Dim rptGen as WSTestProject.testproject = Nothing
rptGen = New WSTestProject.testproject With {
.Url = "http://x-xxx-xx-xx-01:8080//TestProject/testproject?wsdl",
.Timeout = 1200000
}
Here, WSTestProject is the WebService NameSpace and testproject is the web method.
I am using a feign client for soap and I had the similar issue,Adding the correct namespace to the JAXB request and response object resolve the issue.
The issue was in my environment was the wsdl cache in php. The updated wsdl was not picked by the client and it was referring to the old wsdl.
You can do either one of the following options when you do the development of the web service and test, as the wsdl change during the update/implementation of the web service
Add WSDL_CACHE_NONE to soap client creation
$myServices_client = new SoapClient($myServices_wsdl_URL, array('cache_wsdl' => WSDL_CACHE_NONE) );
Set initialization parameter
ini_set("soap.wsdl_cache_enabled", 0);
Adding '/' will work for you.
Error: Cannot find dispatch method for {http://zzz.com}servicename
Not Working Request: xmlns:ser='http://zzz.com'>
Working Request: xmlns:ser='http://zzz.com/'>
I picked up an old Java project. I am not sure how it worked before, but I saw similar error and the reason was in wrong SOAP HTTP endpoint binding at server side.
Doesn't work:
Endpoint.create(HTTPBinding.HTTP_BINDING, servicePortType);
Works:
Endpoint.create(SOAPBinding.SOAP11HTTP_BINDING, servicePortType);