Spring Integration - url-variable not working in http:outbound-gateway - java

In order to send http request to dynamic urls based on message headers...
I am trying to set the url value from Message header as follows:
<int-http:outbound-gateway id="httpOutboundGateway" request-channel="fromMyQueue"
url="{outboundGatewayUrl}" reply-channel="nullChannel"
http-method="POST" expected-response-type="java.lang.String" charset="UTF-8">
<int-http:uri-variable name="outboundGatewayUrl" expression="headers['X-CUSTOM-HTTP-REQUEST-URL']" />
But this is not working.
Apparently {outboundGatewayUrl} value is not being replaced at all.
This works if i replace the {outboundGatewayUrl} with actual URL.
Error Message:
Caused by:
org.springframework.integration.MessageHandlingException: HTTP request execution failed for URI [{outboundGatewayUrl}]...
Caused by:<br> java.lang.IllegalArgumentException: URI is not absolute
at java.net.URI.toURL(URI.java:1080)
at org.springframework.http.client.SimpleClientHttpRequestFactory.createRequest(SimpleClientHttpRequestFactory.java:109)
What am i missing here?

It looks like header X-CUSTOM-HTTP-REQUEST-URL doesn't exist in the message.
You will get that error (URI is not absolute) if the expression returns null (i.e. if the header doesn't exist).
I just ran a test and it worked fine for me with a proper header; if you believe the header is correct, you should break down the problem; for example by using a literal expression first...
<int-http:uri-variable name="outboundGatewayUrl" expression="'http://foo/bar'" />
The error message is, perhaps somewhat misleading:
Caused by:
org.springframework.integration.MessageHandlingException: HTTP request execution failed for URI [{outboundGatewayUrl}]...
because it implies the url wasn't expanded. The problem is the expansion is done inside the RestTemplate and the adapter doesn't have access to it.

I think you are missing a $ sign before your {outboundGatewayUrl} and consequently it is not being expanded by SEL. This is also suggested in the error message.

Related

How do I modify the HTTP response code and message in java

My goal is to modify the http response status code and the content that comes with it (not using spring by the way). The current response I'm getting is an HTTP 501 and I would like to modify that response to return an HTTP 200 instead with a custom message.
I've tried using javax.servlet.Filter and found out that that won't work (as far as I know) since I can't modify the response after the filterChain.doFilter() call. I tried redirecting a response using httpResponse.sendError() but didn't work since I'm getting an IllegalStateException telling me about the reponse was already committed or something like that.
I've also tried adding an <error-page>...</error-page> block in my web.xml using a web servlet as the location but apparently that does not work for unsupported methods and invalid headers (tried using a random string as request method; also tried Transfer-Encoding: random as an invalid header); works for invalid uri paths though.
Is there a way to create a general "filter" mechanism where I can modify the response code and message when there's a HTTP error code response?

SAAJ0511: Unable to create envelope from given source error because of an unexpected character

I'm getting the following error while trying to parse a soap request which contains the "\u0001" character in data part of the xml body:
com.sun.xml.internal.messaging.saaj.soap]: createEnvelope - SAAJ0511: Unable to create envelope from given source
Without this character, the code works correctly. However the request is coming from a machine which I can't control, so I need to remove this character at the backend side but I don't know how. I tried to add an interceptor but it didn't work, because it gives the error before processing the interceptor. Do you have any idea?

What is the correct HTTP error code to return, 404 vs 412?

I am working on designing the REST APIs. One of the POST request to create a room in a home takes an input of ID of the home and room name like :
POST /webCall/development/construction
<?xml version="1.0"?><room><home id='110001'/><name>large bedroom</name></room>
So my question here is,suppose the home ID = 110001, doesn't exist in the system, In that case should 404(Resource not found) be the response code or 412(Precondition failed) be the response code.
Possible arguements.
Why 404 : The resource home with ID : 110001 is not found.
Why 412 : The precondition to create a room is that a home should exist,which fails here.
Please provide your suggestions with reasoning, that would help me to take right decision.
412 is incorrect for the reason given by Sotirios.
404 is incorrect because the problem is with the payload, not the addressed resource (URI).
You could use 400 (generic), 409 or 422.
The HTTP spec says the following about the 412 status code
The precondition given in one or more of the request-header fields
evaluated to false when it was tested on the server. This response
code allows the client to place preconditions on the current resource
metainformation (header field data) and thus prevent the requested
method from being applied to a resource other than the one intended.
So this status code would make sense if you were sending an If-Match header with the
entity tag of the resource you're trying to add to.
Assuming you're posting to something like below
/homes/some-identifier/rooms
you should probably be returning a 404, since the resource /homes/some-identifier/rooms does not exist.
If you are actually doing
POST /webCall/development/construction
<?xml version="1.0"?><room><home id='110001'/><name>large bedroom</name></room>
then 409 would probably be the most appropriate. However, I recommend you change your API to POST to the actual home resource.

Include jquery.js and javascript.js in the page

I am trying to include jquery.js and javascript.js files on my page, as proposed in the previous question by passing it through the Servlet class like:
response.getDocument().body().appendChild(new DataNode("<script src=\"" + themeUri
+ "/js/nativeinit.js\" type=\"text/javascript\"></script>",""));
response.getDocument().body().appendChild(new DataNode("<script src=\"" + themeUri
+ "/js/jquery.min.js\" type=\"text/javascript\"></script>",""));
When I see the Console in Browser though I see the messages for both files:
Resource interpreted as Script but transferred with MIME type text/html: "http:8080/uri/js/nativeinit.js". myhost/:47
Resource interpreted as Script but transferred with MIME type text/html: "http:8080/uri/js/jquery.min.js". myhost/:47
And then:
Uncaught SyntaxError: Unexpected token < nativeinit.js:1
Uncaught SyntaxError: Unexpected token < jquery.min.js:1
What is wrong and it cannot read them as script? Why this strange message of unexpected token? What should I change/add?
Update:
I have also added in my web.xml file:
<mime-mapping>
<extension>js</extension>
<mime-type>application/javascript</mime-type>
</mime-mapping>
but problem with the same message remains. I am aware of the fact that #Javascript annotation is the recommended way in vaadin 7, but I think it should work as well on the common way. I do not set Content Type in Servlet Class. I can use there only the class BootstrapPageRespone from https://vaadin.com/api/ , which does not provide the methods from ServletResponse. Otherwise I would have set it also programatically.
check this question: Chrome says "Resource interpreted as script but transferred with MIME type text/plain.", what gives? - maybe when browser requests your script, it gets answer from server as text/html. Check MIME type of your server response.
The recommended approach is to use the #Javascript annotation, as discussed in this article.

Unable to create AZURE VM programmatically

We are trying to create a Virtual Machine through an HTTPClient in Java using the REST API exposed by Azure. We are using the following Request URL and XMLs, but we are getting "Bad request" response.
https://management.core.windows.net/{subscription-id}/services/hostedservices/{existing hoster service name}/deployments
<Deployment xmlns="http://schemas.microsoft.com/windowsazure" xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
<Name>TestVMAnandP</Name>
<Label>bXl2bQ==</Label>
<RoleList>
<Role>
<RoleName>TestVMAnandP</RoleName>
<RoleType>PersistentVMRole</RoleType>
<ConfigurationSets>
<ConfigurationSet>
<ConfigurationSetType>LinuxProvisioningConfiguration</ConfigurationSetType>
<HostName>TestVMAnandP</HostName>
<UserName>root</UserName>
<UserPassword>test</UserPassword>
</ConfigurationSet>
</ConfigurationSets>
<DataVirtualHardDisks>
<DataVirtualHardDisk>
<Lun>10</Lun>
<LogicalDiskSizeInGB>50</LogicalDiskSizeInGB>
</DataVirtualHardDisk>
</DataVirtualHardDisks>
<OSVirtualHardDisk>
<SourceImageName>srini2-srini2-2012-08-23.vhd</SourceImageName>
<MediaLink>http://sriniteststore.blob.core.windows.net/vhds/srini2-srini2-2012-08-23.vhd</MediaLink>
</OSVirtualHardDisk>
<RoleSize>ExtraSmall</RoleSize>
</Role>
</RoleList>
<VirtualNetworkName>MyNetwork</VirtualNetworkName>
</Deployment>
If we try to give a service name same as the vm name in the URL, we are getting 404 Error. We have tried most of the samples given in the web with values replaced, but everything gives us a 400 Error. It would be great if we get some help.
Errors :
Two different kind of errors i am getting :
Error 1 : When i use new <service-name> inside the below URL .management.core.windows.net/<subscription-id>/services/hostedservices/<service-name>/deployments/ ------------------------------------------------------------------- Response message--->Not Found---404
java.io.FileNotFoundException: management.core.windows.net/84cc18f5-5bdd-4c95-9d69-862c12c53507/services/hostedservices/anand/deployments
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at sun.reflect.NativeConstructorAccessorImpl.newInstance(Unknown Source)
Caused by: java.io.FileNotFoundException: management.core.windows.net/84cc18f5-5bdd-4c95-9d69-862c12c53507/services/hostedservices/anand/deployments
at sun.net.www.protocol.http.HttpURLConnection.getInputStream(Unknown Source)
Error 2 : when i use an existing available <service-name> in the below URL management.core.windows.net/<subscription-id>/services/hostedservices/<service-name>/deployments/
Response message--->Bad Request---400
java.io.IOException: Server returned HTTP response code: 400 for URL: management.core.windows.net/84cc18f5-5bdd-4c95-9d69-862c12c53507/services/hostedservices/azurecogservice/deployments
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at sun.reflect.NativeConstructorAccessorImpl.newInstance(Unknown Source)
Caused by: java.io.IOException: Server returned HTTP response code: 400 for URL: management.core.windows.net/84cc18f5-5bdd-4c95-9d69-862c12c53507/services/hostedservices/azurecogservice/deployments
at sun.net.www.protocol.http.HttpURLConnection.getInputStream(Unknown Source)
---------------------VALID XML-------------------------------------------------------------
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<Deployment xmlns="http://schemas.microsoft.com/windowsazure">
<Name>190bed4a</Name>
<DeploymentSlot>Production</DeploymentSlot>
<Label>190bed4a</Label>
<RoleList>
<Role>
<RoleName>SuseOpenVm_rolec8fc</RoleName>
<RoleType>PersistentVMRole</RoleType>
<ConfigurationSets>
<ConfigurationSet>
<ConfigurationSetType>LinuxProvisioningConfiguration
</ConfigurationSetType>
<HostName>SuseOpenVm_rolec8fc</HostName>
<UserName>anandsrinivasan</UserName>
<UserPassword>Cloud360</UserPassword>
<DisableSshPasswordAuthentication>false</DisableSshPasswordAuthentication>
</ConfigurationSet>
<ConfigurationSet>
<ConfigurationSetType>NetworkConfiguration</ConfigurationSetType>
<DisableSshPasswordAuthentication>false</DisableSshPasswordAuthentication>
<InputEndpoints>
<InputEndpoint>
<LocalPort>22</LocalPort>
<Name>SSH</Name>
<Port>22</Port>
<Protocol>TCP</Protocol>
</InputEndpoint>
</InputEndpoints>
</ConfigurationSet>
</ConfigurationSets>
<OSVirtualHardDisk>
<MediaLink>https://portalvhdsvf842yxvkhbg4.blob.core.windows.net/vhds/190bed4a.vhd</MediaLink>
<SourceImageName>SUSE__openSUSE-12-1-20120603-en-us-30GB.vhd</SourceImageName>
</OSVirtualHardDisk>
<RoleSize>Small</RoleSize>
</Role>
</RoleList>
<VirtualNetworkName>anand360NW</VirtualNetworkName>
</Deployment>
Whenever I'm having issues with the REST API I first try to complete what I'm trying to do through the portal. In your case I tried creating a Linux VM (TestVMAnandP) with username root and password test. I immediately noticed the following errors:
User Name 'root' is not allowed
Password should be at least 8 characters
Password should contain 3 of the following:
a lowercase character
a uppercase character
a number
a special character
I have been working on the same thing a while back.
i suggest you check out my implementation of a java REST client that consumes this API at the Cloudify GitHub repo:
https://github.com/CloudifySource/cloudify/blob/master/esc/src/main/java/org/cloudifysource/esc/driver/provisioning/azure/client/MicrosoftAzureRestClient.java
another good reference is the node.js sdk provided my Microsoft. you can browse the code and see where you went wrong :
https://github.com/WindowsAzure/azure-sdk-for-node/blob/master/lib/services/serviceManagement/servicemanagementservice.js
hope it helps
Error code 400/4xx would mean that there is something wrong with the request. And error code 404 specifically says that "The server has not found anything matching the URI given". So can you verify if the information provided in OSVertualHardDisck is correct.
<OSVirtualHardDisk>
<SourceImageName>srini2-srini2-2012-08-23.vhd</SourceImageName>
<MediaLink>http://sriniteststore.blob.core.windows.net/vhds/srini2-srini2-2012-08-23.vhd</MediaLink>
</OSVirtualHardDisk>
Update
Is the the service you are trying to use
http://msdn.microsoft.com/en-us/library/windowsazure/jj157194.aspx
You can see the error code explanations here
http://msdn.microsoft.com/en-us/library/windowsazure/ee460801.aspx
It might just be possible that the target url that you are using is not valid or expected by server.
Service Management API documentation is seriously messed up. I wouldn't be surprised if you're victim of that. One thing you can try is changing the
<LogicalDiskSizeInGB>50</LogicalDiskSizeInGB>
element to
<LogicalSizeInGB>50</LogicalSizeInGB>
under your DataVirtualHardDisk element.
The reason I'm suggesting this is because if you look at the documentation for Get Data Disk (http://msdn.microsoft.com/en-us/library/windowsazure/jj157180.aspx), it mentions that you get LogicalDiskSizeInGB as one of the response element however when you execute this function, the element you get back is LogicalSizeInGB.
Again it's a hunch. Give it a try.
Update
Another thing you might want to do is parse the exception you're getting to get more details. In .Net we get a WebException (Sorry, haven't worked in Java for a long-long time) so what I normally do is read the response of that exception and that returns me an XML with somewhat more details.
Anand, there is a problem with this API. I have implemented this in fluent management and unfortunately the XML is order dependent.
You can cycle between 400 and 500 HTTP exceptions if this is not precise. I would use powershell to write your VM creation in verbose mode and get your application to use the XML in the exact order you see it and it should be fine.
In the next few days I'll be posting up a java service management client example on http://blog.elastacloud.com which consumes a .publishsettings file to make requests which may be helpful for you.

Categories