How to use context path to hit soap webservice? - web-services

I have changed the the context path in property file and after that when I am trying to hit webservice from SOAPUI, I am getting blank page as a response.So, I have given the same value as in context-root of jboss-web.xml. Still, facing the same issue.
server.contextPath=/myvalue
<context-root>/myvalue</context-root>
I have made some changes in SOAPWSConfig class also.
#Bean
public ServletRegistrationBean messageDispatcherServlet(ApplicationContext applicationContext) {
MessageDispatcherServlet servlet = new MessageDispatcherServlet();
servlet.setApplicationContext(applicationContext);
servlet.setTransformWsdlLocations(true);
return new ServletRegistrationBean(servlet,"/myvalue/*");
}
Below is the change I made in my camel route to point the URL:
from("spring-ws:uri:http://{{webservice.ipaddress}}:{{webservice.port}}/{{server.contextPath}}/CCSWebServiceBean/GetScheduleDetailsCCS?endpointMapping=#endpointMapping")
.unmarshal(jaxb).process(ccsServiceProcessor).marshal(jaxb);
}
It was working with a default contextPath value.The URL which I am using to hit from SOAPUI is:
http://10.80.11.65:8080/myvalue/CCSWebServiceBean/GetScheduleDetailsCCS
Please help to resolve this.
Thanks in advance.

To handle endpoint header/property dependence, you should use "recipientList".
In blueprint, it would be something like:
<recipientList><simple>spring-ws:uri:http://{{webservice.ipaddress}}:{{webservice.port}}/{{server.contextPath}}/CCSWebServiceBean/GetScheduleDetailsCCS?endpointMapping=#endpointMapping</simple></recipientList>
Same apply for plain java camel routes.

Related

Spring #RequestMapping for everything except /api/ or /rest/ (negate specific word in regex)

I need a Spring #RequestMapping that I will use to match all non-/api/... paths like /products to forward them to my / (by return "forward:/";) view controller which actually serves index.html contents and causes frontend (React) application to be served so that frontend application can handle this path to render a page.
Please note, that implicitly this #RequestMapping cannot match / as it would end up in infinite recurence and StackOverflowError. It may be worth to exclude index.html also.
In other words, I want my /api/products to be handled "locally" by Spring Boot application, where /products/ should be forwarded to render React app. There is not Apache or Nginx proxy - React app is served by Spring thanks to static resource mappings.
I have studied many similar Stackoverflow questions in this area and none of them is working.
Important note: I saw cases on Stackoverflow where the problem only supposed to be resolved, just because initially it looked like working (/products/ forwarded and /api/products handled by API Controller), but it actually wasn't, because proposed regex was matching everything and /api/products were handled only by Spring mapping precedences (more specific "wins"), but the same path would actually match the pattern if no other Controller would exist.
This results in inappropriate 404 (or mapping not found) error handling - calling any, even not existing /api/something endpoint ends up with forward to index.html in all answers that I have found, which I want to avoid. Accessing not existing /api/something endpoint should rather end up with no handler found Spring error, not in forward. An example of such solution, is the most popular one, like: #RequestMapping(value = "{_:^(?!api).*$}")
The problem is, whatever pattern I try, it ends up with forwarding all of my test cases (like /api /api/ /api/x /page/ /page/2 or none.
Just some examples of patterns I have tried:
#RequestMapping(value = "{_:^(?!index\\.html|api).*$}")
#RequestMapping(value = "{x:^(?!api).*$}")
#RequestMapping(value = "/{path:^(?!api/).*$}")
#RequestMapping(value = "/{dataType:^.*(?!api).*$}")
#RequestMapping(value = "/{arg:(?!sitemap.xml|api|index.html).*$}")
#RequestMapping(value = "{arg:^(?!api|!index.html).*$}/**")
#RequestMapping(value = "{_:^(?!index\\.html|api).*$}")
Looks like the original regex actually works (e.g. "{_:^(?!index\\.html|api).*$}").
The problem is, Jetty, to display 404 was internally forwarding to /error page which also was subject for that controller mapping! Effectively forwarding to frontend app from public resources instead of rendering error page
Question still valid, but for people that need solution I can propose to forward on filter level:
#Bean
public FilterRegistrationBean nonApiRequestToRootPathForwarderFilterRegistrationbean() {
FilterRegistrationBean<Filter> filterFilterRegistrationBean = new FilterRegistrationBean<>();
filterFilterRegistrationBean.setFilter(new Filter() {
#Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
HttpServletRequest request1 = (HttpServletRequest) request;
if (!request1.getRequestURI().startsWith("/api/") && !request1.getRequestURI().equals("/")) {
RequestDispatcher requestDispatcher = request.getRequestDispatcher("/");
requestDispatcher.forward(request, response);
return;
}
chain.doFilter(request, response);
}
});
return filterFilterRegistrationBean;
}

simple azure web service, http404 error on publish when adding /dowork to URL

I am trying my first web app service using Azure services. I've created it in VS, and it works locally. All it does it return a string that says "hello user" is JSON.
[ServiceContract(Namespace = "")]
[AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
public class Service1
{
// To use HTTP GET, add [WebGet] attribute. (Default ResponseFormat is WebMessageFormat.Json)
// To create an operation that returns XML,
// add [WebGet(ResponseFormat=WebMessageFormat.Xml)],
// and include the following line in the operation body:
// WebOperationContext.Current.OutgoingResponse.ContentType = "text/xml";
[OperationContract]
[WebGet(UriTemplate = "/DoWork")]
public string DoWork()
{
// Add your operation implementation here
return "hello user";
}
// Add more operations here and mark them with [OperationContract]
}
}
Problem is when I publish it, says successful. I can see it running on portal.
When I goto published site I get the standard THIS WEB APP HAS BEEN SUCCESSFULLY CREATED, but... when I add the /DoWork to the URL I get HTTP error 404.
I know I must be missing something simple...
any ideas?
you're missing the name of the service. In your case would be something like:
http://engineappservicev001.azurewebsites.net/something.svc/dowork
More info in here:
http://www.codeproject.com/Articles/571813/A-Beginners-Tutorial-on-Creating-WCF-REST-Services

How can I get this working with a GET or should it be a POST with REST Service in Spring

I am working on some web servers and I have to sent some data to the web service and get back a status code.. I am thinking maybe this should be a POST and not a GET but I would like to hear from all the pros out on the internet.
Here is my client code using Spring RESTTemplate
vars.put("lastName", "JOHN");
vars.put("firstName", "SMITH");
vars.put("middleInitial", "");
vars.put("socialSecurityNumber", "111-11-1111");
vars.put("Type","A");
vars.put("FileNumber","");
vars.put("EISNumber","");
String jsonreturn = restTemplate.getForObject("http://" + mRESTServer.getHost() + ":8080/services/api/checkstatus", String.class, vars);
Now here is my service side code (Spring MVC RESTful service). I would think all the fields I entered in the client would be in the ModelMap object but its not
#RequestMapping(value = "/checkstatus", method = RequestMethod.get)
#ResponseBody
public ResponseEntity<String> getCheckEnrollStatus(ModelMap model) throws ResourceNotFoundException
{
logger.debug("Looking for Status: " + model.toString());
}
So I have two questions:
1) Should I change the GET to a POST due to senting alot of data to the server?
2) If I leave it as a get why is my ModelMap emply?
Please help me out
For your ModelMap to be populated you probably need to annotate it with #RequestBody.
As the comment has pointed out you can't have a request body with a GET as per the specification. So you would either need to make the parameters part of the URL and use get or convert to POST.
Though POST seems to not fit with the purpose of your call.
Normally I'd say this should be a GET, but I noticed you have socialSecurityNumber as one of your parameters. You definitely do NOT want that to be part of your URL. Check out RFC 2616 section 15.1.3
Authors of services which use the HTTP protocol SHOULD NOT use GET based forms for the submission of sensitive data, because this will cause this data to be encoded in the Request-URI. Many existing servers, proxies, and user agents will log the request URI in some place where it might be visible to third parties. Servers can use POST-based form submission instead
Do a POST.
get as it is not changing anything onserver just returning data here is the spec.
Use request parameters like this
#RequestMapping(value = "/checkstatus", method = RequestMethod.get)
#ResponseBody
public ResponseEntity<String> getCheckEnrollStatus(#RequestParam final Long id)
or uri parameters, like
#RequestMapping(value = "/checkstatus/{id}", method = RequestMethod.get)
#ResponseBody
public ResponseEntity<String> getCheckEnrollStatus(#PathVariable final Long id) throws ResourceNotFoundException
{

Trouble with SOAP request from Flex

SUM: I ended up having to form the XML manually. I also had to create an Operation and use its send(); method rather than just doing something like WebService.MyServiceFunction(); - not sure why that was the case.
I send off the request as follows:
var xm:XML =
<SetPropertiesForCurrentUser xmlns="http://asp.net/ApplicationServices/v200">
<values xmlns:d4p1="http://schemas.microsoft.com/2003/10/Serialization/Arrays" xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
<d4p1:KeyValueOfstringanyType>
<d4p1:Key>{obj.Key}</d4p1:Key>
<d4p1:Value xmlns:d6p1="http://www.w3.org/2001/XMLSchema" i:type="d6p1:string">{obj.Value}</d4p1:Value>
</d4p1:KeyValueOfstringanyType>
</values>
</SetPropertiesForCurrentUser>;
var profileService:WebService = new WebService();
profileService.useProxy = false;
profileService.loadWSDL(url);
var o:Operation = profileService.SetPropertiesForCurrentUser;
o.send(xm);
Here’s my scenario:
I have ASP.NET web services to handle authentication, user roles, and user profiles (default ASP.NET AuthenticationService, RoleService, and ProfileService, to be exact).
So from my Flex web app, I am able to successfully call the ASP.NET service. For example, something like this works fine:
var profileService:WebService = new WebService();
profileService.useProxy = false;
profileService.GetAllPropertiesForCurrentUser.addEventListener("result",getAllPropertiesForCurrentUser_EventHandler);
profileService.addEventListener("fault",getAllPropertiesForCurrentUserFault_EventHandler);
profileService.loadWSDL(url);
profileService.GetAllPropertiesForCurrentUser();
I run into trouble when I need to pass a Dictionary object to another function on the service (SetPropertiesForCurrentUser). The .NET service asks for this type of value:
System.Collections.Generic.IDictionary(Of String, Object)
Here are the two pertinent entries from the web.config entry from my ASP.NET service:
<properties>
<clear/>
<add name="coordinateFormat" />
</properties>
...
<profileService enabled="true"
readAccessProperties="coordinateFormat"
writeAccessProperties="coordinateFormat"/>
So after putting together a SOAP request from a Silverlight app (which works as expected) I’ve narrowed it down to a difference in the XML request sent to the SOAP handler:
From Flex:
<tns:Value>DMS</tns:Value>
From Silverlight:
<d4p1:Value xmlns:d6p1="http://www.w3.org/2001/XMLSchema" i:type="d6p1:string">DMS</d4p1:Value>
If I take the request generated by Flex, catch it with Fiddler, modify that one line to include the “type” namespace – it works.
Anyone have an idea how I can get that namespace onto my variable that is passed to the SOAP handler from Actionscript? Here is my code for sending off that SetPropertiesForCurrentUser function:
var obj:Object = {};
obj["Key"] = "coordinateFormat";
obj["Value"] = DMS;
var profileService:WebService = new WebService();
profileService.useProxy = false;
profileService.SetPropertiesForCurrentUser.addEventListener("result",setPropertiesForCurrentUser_EventHandler);
profileService.addEventListener("fault",setPropertiesForCurrentUserFault_EventHandler);
profileService.loadWSDL(url);
profileService.SetPropertiesForCurrentUser(new ArrayCollection([obj]),false);
Thanks,
Josh
The default SOAPEncoder that is used is some what limited in its capabilities (like not including the type attribute you mentioned above). Luckily, there is a way to control that by writing your own encoder.
see this link at adobe (read part about using custom web service serialization) Link on Adobe's Site

Unable to set headers in apex web service callouts in salesforce

I'm currently trying to call Amazon Product Retail Web Service in Salesforce.
As I mentioned in
Getting WSDL parse error while generating Apex code from WSDL in Salesforce
I was initially unable to generate apex stub class, but I followed the method suggested by #Ballinger and created apex class. I wrote an apex class to use that stub and to set request parameters. The class i wrote is as follows
public class AmazonProductStubNew
{
public static void getResults()
{
System.Debug(' getResults start ');
AmazonWS.AWSECommerceServicePortUS stub = new AmazonWS.AWSECommerceServicePortUS();
stub.inputHttpHeaders_x = new Map<String,String>();
stub.inputHttpHeaders_x.put('AWSAccessKeyId','MyAmazonAWSAccessKeyId');
stub.inputHttpHeaders_x.put('Timestamp','2012-11-28T12:11:30Z');
stub.inputHttpHeaders_x.put('Signature','Encrypted Secret Code');
String MarketplaceDomain = '';
String AWSAccessKeyId = 'MyAmazonAWSAccessKeyId';
String AssociateTag = '';
String XMLEscaping = '';
String Validate = '';
AmazonWS.ItemSearchRequest Shared = new AmazonWS.ItemSearchRequest();
Shared.SearchIndex = 'DVD';
AmazonWS.ItemSearchRequest[] Request = new AmazonWS.ItemSearchRequest[1];
Request[0] = new AmazonWS.ItemSearchRequest();
Request[0].Title = 'Inception';
AmazonWS.ItemSearchResponse_element response = stub.ItemSearch(MarketplaceDomain,AWSAccessKeyId,AssociateTag,XMLEscaping,Validate,Shared,Request);
AmazonWS.Items_element[] localItems = response.Items;
System.Debug(localItems[0].TotalResults);
}
}
Even though I've added HTTP headers to stub, I'm not getting it in XML Request message
XML Request is as follows
<?xml version="1.0" encoding="UTF-8"?>
<env:Envelope xmlns:env="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<env:Header />
<env:Body>
<ItemSearch xmlns="http://webservices.amazon.com/AWSECommerceService/2011-08-01">
<MarketplaceDomain>
</MarketplaceDomain>
<AWSAccessKeyId>MyAWSAccessKeyId</AWSAccessKeyId>
<AssociateTag></AssociateTag>
<XMLEscaping></XMLEscaping>
<Validate></Validate>
<Shared><SearchIndex>DVD</SearchIndex></Shared>
<Request><Title>Inception</Title>
</Request></ItemSearch>
</env:Body></env:Envelope>
Since headers are not there in SOAP Request, There is a SOAP fault asking for Signature from Amazon Server.
As you can see, I'm new to Salesforce Apex. I followed the steps in
http://www.salesforce.com/us/developer/docs/apexcode/index_Left.htm#StartTopic=Content/apex_web_services_wsdl2apex.htm#http_header_support
to set the headers.
Any idea on why the header isn't getting added?
P.S I added headers manually and tried in SOAP UI, I'm getting proper response.
Thanks :)
I think you're using wrong functions :) (question is indeed confusing).
SOAP (or generally HTTP) communication consists of sending headers and actual message (payload if you like). Headers are short text thingies, message is often a giant XML.
Your code is setting HTTP headers (which are used in web communication to authenticate, provide info about your browser, preferred languages, set cookies, return status codes like 404 page not found...) Please don't be offended with the "for dummies" but I realize the wikipedia article is a bit too much, this might be simpler: http://net.tutsplus.com/tutorials/other/http-headers-for-dummies/
And what I suspect Amazon's webservice wants is just some fields inside the <env:Header>...</env:Header> tag? Just check the generated apex code for existence of subclass called "Header" (you can also search for the variable names like "Signature". This is going to be a total wild guess but I think you'll have to write something like that:
AmazonWS.AWSECommerceServicePortUS stub = new AmazonWS.AWSECommerceServicePortUS();
AmazonWS.Header h = new AmazonWS.Header();
h.AWSAccessKeyId = 'MyAmazonAWSAccessKeyId';
h.Timestamp = '2012-11-28T12:11:30Z';
h.Signature = 'Encrypted Secret Code';
stub.Header = h; // plug it into the request
// create and plug other required tags
AmazonWS.ItemSearchRequest Shared = new AmazonWS.ItemSearchRequest();
Shared.SearchIndex = 'DVD';
AmazonWS.ItemSearchRequest[] Request = new AmazonWS.ItemSearchRequest[1];
Request[0] = new AmazonWS.ItemSearchRequest();
Request[0].Title = 'Inception';
// ...
Now, to make it more confusing you might still have to use a HTTP header, there's a special one called SOAPAction. But generally speaking I believe you're after placing your data in the XML, not in http headers.
Funny enough, I've downloaded the Java example from http://aws.amazon.com/code/Product-Advertising-API/2478 and if I read it correctly they're passing the signature in the URL (endpoint), not in the XML. Probably because it's a REST GET method (if you can access that API it could save you a lot of hair pulled, SOAP is clunky).