I am trying to configure spring integration using annotation. Instead of payloadqnameendpoint mapping I would like to use URI endpoint mapping. I found many examples with default URI endpoint but I required an annotation example without default end point.
Let's take a look to the AnnotationActionEndpointMapping support in the Spring WS! As you see it is based on the division between POJO methods and annotations on the them. The POJO is a main word there. This kind of framework magic allow us to separate low-level protocol from end-application business logic. From other side Spring Integration's AbstractWebServiceInboundGateway implements MessageEndpoint meaning that the whole SOAP hard work will be done in this implementation. It isn't a POJO.
Of course this topic is a different story, but you should understand from here that MessageEndpoint and MethodEndpoint work a bit different. At least they do messaging logic from different levels of SOAP request.
So, we really can't map <int-ws:inbound-gateway> with #Action or similar just because it is a whole SOAP endpoint already.
From other side, having AnnotationActionEndpointMapping from Java config, you can fully get rid of <int-ws:inbound-gateway> and configure your Endpoint to delegate desired #Action to the methods of #MessagingGateway. And it will work beucase the hard SOAP work has been done already by Spring WS framework.
I don't know you that this code will work, but you can check or let me know and I'll test it and come back to again:
#Endpoint
#MessagingGateway
public interface OrderEndpoint {
#Action("http://samples/RequestOrder")
#Gateway(requestChannel = "getOrderChannel")
Order getOrder(OrderRequest orderRequest);
#Action("http://samples/CreateOrder")
#Gateway(requestChannel = "createOrderChannel")
void order(Order order);
}
Related
I'm writing some functional tests in play, however I want to test my stack isolated from other http endpoints.
Is there a mechanism for me to say "Direct WS calls to this set of canned responses" or some other way of stubbing out calls to http endpoints that won't be available for automated tests?
Alternatively, how does fakeApplication config get presented to the rest of the application so I can just set the URL to some localhost server which I'll build myself to provide canned responses
You could create a structural type that mimics the WS signature and use that in your code.
type WSLike = {
def url(url: String): WSRequestHolder
}
Then you can inject your own version of a WSLike class. In combination with a mock library I guess you could do about anything you want.
As for the second question. You could call it like this:
val url = Play.current.configuration
.getString("my.webservice.url")
.getOrElse(throw new PlayException(
"Configuration error",
"Could not find my.webservice.url in settings"))
WS.url(url)
Then in your application.conf add the correct url. You can supply a different one using the FakeApplication.
FakeApplication(additionalConfiguration =
Map("my.webservice.url" -> "http://localhost/service"))
I’ve got a Web API that I’ve added [Authorize] attributes to, which means that the unit tests I had previously now fail due to them being unauthorised. Here’s a sample of a basic test along with an initialiser method:
[TestInitialize]
public void CreateServer() {
var config = new HttpConfiguration();
WebApiConfig.Configure(config); // Create the routes
var server = new HttpServer(config);
this.client = new HttpClient(server);
}
[TestMethod]
public void MyThings_GET_Returns_All_MyThings() {
var response = this.client.GetAsync("http://localhost/api/1.0/mythings").Result;
var mythings = response.Content.ReadAsAsync<IEnumerable<MyThing>>().Result;
Assert.AreEqual(HttpStatusCode.OK, response.StatusCode);
Assert.AreEqual(4, mythings.Count());
}
What I’m wondering is if there’s any way that I can either make my test log in so that it passes the authorization filter, or if there’s any way that I can pass as ASPXAUTH cookie along with the HttpClient request? Or another way of passing authorization that I haven’t thought of?
Nothing I’ve tried seems to work and I’m struggling to find any helpful info anywhere.
Thanks in advance.
What does your Authorize attribute do when it performs the authorization check? There are quite a few options that come to mind:
Have the authorize filter support multiple means of getting the "authorization token" that it requires (e.g. through an HTTP header or a querystring parameter, etc)
Right after your test initialization, clear out the filter from the configuration (so that it is not called at all). If you choose to go this route then you may wish to pop in a new filter that sets any authorization values that might be used further along the pipeline
If you are using dependency injection, move the "authorization check" into some sort of IAuthorize location that can be updated in your configuration
I would also recommend using RestSharp for making queries to your endpoints as it does a very good job of specifying headers, parameters, etc.
I decided that the way I was going about the problem was fundamentally wrong. Using cookie-based authorisation with Web API is just not a good idea, so I’ve decided to get rid of the authorize attributes and perform API-Key-based authentication instead. This makes it easier to test as I can just pass the correct API key in the request, but also means that I’m not relying on cookies for authorisation.
DotNetNuke 6.2 has a Services Framework that does something similar
http://www.dotnetnuke.com/Resources/Wiki/Page/DotNetNuke-6-2-Developer-Quick-Start.aspx#Services_Framework_18
The single biggest convenience of Services Framework is that authentication, authorization and establishing a DotNetNuke context are all built in.
How do I integrate ServiceStack (http://servicestack.net) with DotNetNuke to provide authentication, authorization and establish a DotNetNuke context? Any pointers?
I wrote the DNN implementation, so I can tell you about how it works. I don't know the details of ServiceStack so I can't tell you how to apply it there. When I first set out to build this, I expected it to be much more complicated than it actually is. You really only need a handful of calls into the core.
Establishing context and authentication occurs during initialization of the DnnController. One of the great things about DNN being all open source is that all these sort of details are public. Here is a link to the DnnController.cs
And here are the most interesting bits:
protected override void Initialize(RequestContext requestContext)
{
base.Initialize(requestContext);
LoadDnnContext(requestContext.HttpContext);
AuthenticateRequest(requestContext.HttpContext, PortalSettings.PortalId);
}
protected virtual void AuthenticateRequest(HttpContextBase context, int portalId)
{
if (!context.Request.IsAuthenticated)
{
BasicAuthenticator.Instance.TryToAuthenticate(context, portalId);
}
if (!context.Request.IsAuthenticated)
{
DigestAuthenticator.Instance.TryToAuthenticate(context, portalId);
}
MembershipModule.AuthenticateRequest(context, true /*allowUnknownExtension*/);
}
protected virtual void LoadDnnContext(HttpContextBase context)
{
var domainName = TestableGlobals.Instance.GetDomainName(context.Request);
var alias = TestablePortalAliasController.Instance.GetPortalAliasInfo(domainName);
int tabId;
ValidateTabAndModuleContext(context, alias.PortalID, out tabId);
var portalSettings = new PortalSettings(tabId, alias);
context.Items["PortalSettings"] = portalSettings;
}
The Service Framework forces all routes into the form {unique portal path}/DesktopModules/{ModuleName}/API/{url} . The unique portal path is important to easily identifying the portal to which the request was sent. In most cases DNN will allow a URL of the form /Default.aspx?portalid=n, but Service Framework won't accept that, it requires that the request path match the portal alias e.g. mysite.com/childportal/... This requirement ensures that GetDomainName() will work.
I should mention that the TestableXXX classes are in the Internal namespace and therefore are not part of the official public API, and are subject to breaking changes between releases. Most of the methods on the classes have a public analog which is harder to mock but otherwise equivalent. If it is reasonable for you to make small code fixes before upgrading your servers, feel free to use the Testables. If you don't have complete control over the upgrades of your servers you should avoid the .Internal namespaces.
Service Framework supports authentication against the permission of a specific module instance. Services tied to a module must provider tab and module ids. If your services are not module specific you may omit this, and use a tabid of -1 in the PortalSettings.
ServiceFramework has it's own implementations of basic and digest auth since MVC does not provide them. I beleive that ServiceStack does provide Basic and Digest, so you probably only need to make the call to MembershipModule.AuthenticateRequest().
I am working on web services POC. I need to develop a Spring-based web services, that use XML/HTTP i.e. HTTP binding (NOT SOAP/HTTP) so that I can invoke a web-service with URL parameters like the one example described in the WSDL specification especially a GET with query parameters.
I am unable to map the URL's query-parameter to the end-point's (#EndPoint) method parameter.
Is it possible to develop such a web-service (XML/HTTP bound) with spring-ws?
Is it possible to invoke such a service with GET request + query string?
Let me know for any such examples/tutorials.
Please take a look at this page (http://static.springsource.org/spring/docs/3.0.0.M3/spring-framework-reference/html/ch18s02.html). Assuming that you are using spring 3, I believe you should find some relief there.
Based your question, I assume you already have the DispatcherServlet declared and mapped in web.xml. The trick, then, is to pull out the arguments. The page indicates how to pull arguments from both the URL (which I believe is your goal) and from the request body.
Good luck and write back if anything is unclear.
We have HTTP webservices that are RPC. They return XML representing the object the either retrieved or created. I want to know the advantages (if any) of "restifying" the services.
POST http://www.example.com/createDoodad
GET http://www.example.com/getDoodad?id=13
GET http://www.example.com/getWidget?id1=11&id2=45
POST http://www.example.com/createWidget
POST http://www.example.com/createSprocked
One thing I see is that we don't need representations for EVERY resource and we don't need to support all operations (GET, PUT, POST, DELETE) on all resources either.
Basically my question is this.
Convince me that I should be using restful services instead of RPC over HTTP and what would those restful services should be?
For one it's all about semantics, a URI is a Uniform Resource Indicator. HTTP provides methods to GET, POST, PUT, and DELETE a resource. HTTP headers specify in which format I want to recieve or send the information. This is all readily available through the HTTP protocol.
So you could reuse the same URL you use for HTML output to get XML, JSON in a way that HTTP was meant to be used.
XML-RPC and SOAP are based on calling methods that are described by an XSD or WSDL file whilst REST is based on getting/modifying resources. The difference is subtle but apparent. The URL solely describes the resource and not the action as is often the case with SOAP and XML-RPC.
The benefits of REST are that you can utilize HTTP verbs to modify a resource as supposed to a method call that could be named create/new/add, etc. Meaningful HTTP status codes instead of different kinds of error responses and being able to specify different formats on the same resource in a standard way.
You also don't have to accept ALL the verbs on a RESTful resource, for example if you want a read-only resource just return a 405 status code Method Not Allowed on any verb which isn't GET.
Should you redo your RPC calls to REST ? No, I don't think so. The benefits don't outweigh the development time. Should you learn REST when setting up a new Webservice ? Yes, I personally do think so, consuming a REST resource will feel a lot more natural and can grow much more rapidly.
EDIT
Why I feel REST wins over XML-RPC/SOAP is that when developing websites you already aggregate all the neccessary data for the output to HTML, you also write validating code for POST bodies. Why should you change to a different protocol just because the transport markup changes?
This way when you design a new website (language agnostic) if you really think of URI's as resources you basically use your URI's as method calls with the HTTP verb prefixing the method call.
That is, a GET on /products/12 with an HTTP header Accept: application/json; basically (imaginary) translates to getProducts(12,MimeType.Json).
This 'method' then has to do a couple of things
Check if we support JSON as a MIME type. (Validate request)
Validate request data
Aggregate data for product 12.
Format to JSON and return.
If for some reason in the next 4 years YAML is going to be the next big craze and one of your consumers wishes to talk to you in that way this MIME type is plugged in a lot easier than with regular web services.
Now product 12 is a resource you most likely also want to accept HTML MIME types on to display said product, but for a URI like /product/12/reviews/14/ you don't need an HTML counterpart, you just want your consumers to be able to post to that URL to update(PUT)/delete(DELETE) their own review.
In thinking of URIs strictly as resources, not just a location of a web page, and these resources in turn combined with the HTTP request to method invocations on the server side leads to clean (SEO friendly) URLs and (more importantly?) ease of development.
I'm sure there are frameworks in any language that will automatically do the mapping of URIs to method invocations for you. I can't recommend one since I usually roll out my own.
ASP.NET MVC also works on the same principle, but in my opinion it doesn't produce RESTful URIs. ASP.NET MVC makes the verb part of the URI by default having said that it's good to note that by no means does ASP.NET MVC force this (or anything for that matter) upon you.
If you're going to choose a framework at the very least they should:
Bind URI's to methods on the server
Support Object to JSON/XML, etc. serialization. It's a pain if you have to write this yourself although, dependent on the language, not neccessary all too difficult.
Expose some sort of type safe request helpers to help you determine what was requested without parsing the HTTP headers manually.
Try taking the verbs out of your URLs:
POST http://www.example.com/Doodad
GET http://www.example.com/Doodad/13
GET http://www.example.com/Widget/11/45
POST http://www.example.com/Widget
POST http://www.example.com/Sprocked
Query strings shouldn't be used for accessing a resource in a hierarchical, non-query manner. Query strings are usually ignored when caching, which is dangerous and slow.