How to add custom parameter to Camel's Spring web service component - web-services

My application uses versions 2.19.0 of camel-core and camel-spring-ws. I need it to send a response message to a Client's service using Camel's SpringWebserviceComponent.
It's all pretty standard apart from the client's url, it contains a parameter at the end with no value e.g. https://client-service.com/path/index.php?protocol+web_service
I have never seen a URL like this before but the client states that the parameter on the end (after the question mark and with no value) maps to a controller in their application.
When I try to feed this into my application, I get a org.apache.camel.ResolveEndpointFailedException.
I've looked through the source code of the SpringWebserviceComponent and line 129 of org.apache.camel.impl.DefaultComponent (of which SpringWebServiceComponent extends) validates the URL parameters and throws the ResolveEndpointFailedException if any of the parameters are not valid parameters for the Spring web service component, as listed here: https://camel.apache.org/spring-web-services.html. Ofcourse, protocol+web_service is not a valid parameter for the SpringWebserviceComponent and so the exception is thrown.
This validation is only conducted if the SpringWebServiceEndpoint's isLenientProperties() method returns false, which it is hard-coded to do.
Can anyone suggest any other ways to make the SpringWebServiceComponent accept this url including its non-standard parameter?

Sorry this is not support out of the box, you can try to extend the spring-ws component and override some of the methods that setup the endpoint and whatnot, and then add your hack for this "invalid" url that your client uses.

Related

passing custom messages downstream in spring cloud function's MessageRoutingCallback

Hey I m using MessageRoutingCallback to route to a function in spring cloud functions. It needs FunctionRoutingResult for routing. I also wanted to edit the message. The spring cloud docs says.
"Additionally, the FunctionRoutingResult provides another constructor allowing you to provide an instance of Message as second argument to be used down stream".
But the problem is the constructor with Message type in FunctionRoutingResult is internal and cannot be accessed outside.
Am I doing something wrong here. Any insight would be helpful
Couple of things.
As the documentation explains it is made to assist with routing decisions. For example if routing decision should be made based on payload which may need to be temporarily converted.
The reality is that it is a very bad practice to let framework make such decisions based on the payload, since payload is a privileged information. Similar to the letter in the envelope where mailman does not read the actual letter to make proper routing decisions. .. those all come from the envelope itself. So I will actually update the documentation to remove that paragraph.
And it is definitely not there to modify the message. That would be improper use of MessageRoutingCallback. To modify message you can use function composition. For example MessageRoutingCallback you check some header in the incoming message, determined that the function name should be foo but then actually output modifier|foo as function definition.

Passing a colon (:) to a webservice in a browser (for testing)

I would like to pass a date string to a web service for testing, using a browser. I've tried Chrome and Firefox and both error out with this:
Server Error in '/' Application.
A potentially dangerous Request.Path value was detected from the client (:
The web service (RESTful) is accessed like this:
http://localhost:52936/Accounts/mod_date/2015-05-13T15%3A15%3A19
I've tried enclosing the date in quotes, but get the same error. Is this possible?
Try a QueryString Parameter
Since you are just performing testing, you should be able to pass your stringified DateTime value as a querystring parameter and it should avoid your service throwing a fit :
/Accounts/mod_date?yourDateParameterName=2015-05-13T15:15:19
Or if you wanted a more in-depth approach, you could consider using a suggestion like the one mentioned in this related discussion.
Explicitly Allow : Characters
Scott Hanselman covers the idea of explicitly allowing certain characters to be passed to a service via a URL in this blog post. It basically allows you to define which values are considered "dangerous" when passed in and would simply involve you changing the requestPathInvalidCharacters setting within the web.config of your application from :
<httpruntime requestvalidationmode="2.0">
requestPathInvalidCharacters="<,>,*,%,:,&,\"
/>
</httpruntime>
to :
<!-- Removes the colon ':' as a dangerous parameter -->
<httpruntime requestvalidationmode="2.0">
requestPathInvalidCharacters="<,>,*,%,&,\"
/>
</httpruntime>
This is obviously very controversial stuff and may not be useful for all scenarios, but it is an option.
Consider Postman (for Testing)
Additionally for testing purposes, you might consider using a service like Postman, which is ideal for performing this type of API testing.

Blank value in web service for Int64 type

I consume a web service that has a numeric element. The Delphi wsdl importer sets it up as Int64.
The web service allows this element to be blank. However, because it is defined as Int64, when I consume the web service in Delphi without setting a value for it, it defaults to 0 because it's an Int64. But I need it to be blank and the web service will not accept a value of 0 (0 is defined as invalid and returns an error by the web service).
How can I pass a blank value if the type is Int64?
Empty age (example)
<E06_14></E06_14>
could have a special meaning, for example be "unknown" age.
In this case, the real question is how to make the field nillable on the Delphi side.
From this post of J.M. Babet:
Support for 'nil' has been an ongoing issue. Several built-in types of
Delphi are not nullable. So we opted to use a class for these cases
(not elegant but it works). So with the latest update for Delphi 2007
I have added several TXSxxxx types to help with this. Basically:
TXSBoolean, TXSInteger, TXSLong, etc. TXSString was already there but
it was not registered. Now it is. When importing a WSDL you must
enable the Use 'TXSString for simple nillable types' option to make
the importer switch to TXSxxxx types. On the command line it is the
"-0z+" option.
The DocWiki for the Import WSDL Wizard also shows two options related to nillable elements:
Process nillable and optional elements - Check this option to make the WSDL importer generate relevant information about optional
and nillable properties. This information is used by the SOAP runtime
to allow certain properties be nil.
Use TXSString for simple nillable types - The WSDL standard allows simple types to be nil, in Delphi or NULL, in C++, while Delphi
and C++ do not allow that. Check this option to make the WSDL importer
overcome this limitation by using instances of wrapper classes.

Opening a carbon c++ program from a custom url on OSx

I have been able to set the plist for my project to open the project with a given url. However, I can't get it to pass params to the application (custom urls are built based on the user)
Is there a way to pass the params as command line arguments?
the scheme is essentially
url:userid
I need to be able to get the user id in the application.
Is there a way to do this? I know with cocoa you can create an app delegate to handle this but I need a carbon way to do it.
Thanks in advance!
Install an Apple Event handler to recognize URLs (both the suite and the event name have the same four-character code, 'GURL').
The event's direct object is a URL string. I would expect that string to contain the entire original URL, including any parameters that were encoded into it (e.g. if your custom scheme was xyz://some/data?param1=abc&param2=def, you should receive all of that).
Another important step is to register as a handler for that URL type in your Info.plist file. Read up on CFBundleURLTypes for more.

Does Apache Thrift validate parameters?

I'm considering using Apache Thrift for a PHP server that implements web services.
If my web service were to be defined to accept two parameters - a user name as a string, and a password as an integer - would thrift validate that parameters of those types were supplied by the client, or do I still need to perform validation on the server?
I'm not asking here for the purposes of sanitising input, but rather for returning meaningful error responses to clients, and whether if a service is invoked with incorrect parameters requests will even be made to the server.
To my understanding, the check - if any - is performed at "library level", where the local types are translated into Thrift types, where the code generation happens. In other words, it will depend on the bindings for the specific language you are using (PHP, Erlang, whatever), to raise meaningful - or not - errors if types are not respected. But I have to look into it a bit more.
It basically depends on what kind of validation we are talking.
If the parameters need to be set, you could make them "required". In that case, the fields are checked in most language implementations (not in all) during deserialization and an error is thrown whenever a reuirwed Parameter is missing. However, required comes at the cost of potential problems with versioning: you can't omit a required field once the API has been published, or it will break compatibility otherwise.
The presence of normal ("optional") values can typically be checked by means of the _isset flags, which exist for exactly this purpose. This is something that your own code is responsible for - Thrift does provide the messaging mechanisms, but of course not the interpretation of your data.
If validation in your case means, that the data Format (string and number) should be checked: Because the code for both Client and Server is generated from the Thrift IDL file, the implementation will use the correct field serialization and deserialization method according to the IDL file:
Service sample
{
bool Login( 1: string Name, 2: i32 pwd)
}
If you Need to Change for whatever reason the Password from i32 into string, technically this results in two changes:
remove the Password field with the ID 2, except if the field is "required"
add a new field with the new ID 3
so it looks this way:
Service sample
{
bool Login( 1: string Name, /*2: i32 _deprecated_pwd*/, 3: string pwd)
}
As field type and field purpose are bound to the numeric field ID, it is highly recommended to use another field ID in such a case, which is so far unused within this scope. It is also recommended to leabve the old fields in the IDL to indicate outdated IDs.
A good reference about this "soft versioning" stuff and the pros and cons of "required" fields can be found in Diwaker Gupta's "Missing Guide".