Spring-ws client from WSDL - wsdl

I have created a POX client (generated from jaxb2 from XSD) using spring-ws, but am confused as to how to create a SOAP client (generated from a WSDL). I am using wsimport to generate stubs, but it seems like this goes 1 step too far for use with spring-ws. The stub actually handles the transport, where as with the POX client, spring handles the transport. So, my question is: is it possible to generate just the transport objects through wsimport, or jaxb2 (like the POX client), or what do I call/send in the WebServiceTemplate?

Yes, you can.
Make sure your XSD is imported from and not embedded in your wsdl.
Point xjc (from Jaxb2) at your xsd and let it generate your classes.
Now check your schema.
If your request and response element have embedded complex types use this:
RequestElement requestElement = new RequestElement();
ResponseElement responseElement = (ResponseElement) webServiceTemplate.marshalSendAndReceive(requestElement);
otherwise (referenced complex types) use this:
RequestType requestType = new RequestType();
JAXBElement<RequestType> request = new ObjectFactory().createRequestType(requestType);
ResponseType responseType = ((JAXBElement<ResponseType>) webServiceTemplate.marshalSendAndReceive(request)).getValue();
RequestElement, ResponseElement, RequestType and ResponseType are of course just examples. Substitute them with whatever classes Xjc generated from your schema.

Related

Can't set mapping for dynamic URL in SpringDoc OpenAPI

I want make Swagger specification for my API. But customers use my API can create and delete some entity on server. Each entity have only one type and can include other entity.
Example of API:
http:/localhost/api/<entity_lv_1>
http:/localhost/api/<entity_lv_1>/<entity_lv_2>
http:/localhost/api/<entity_lv_1>/<entity_lv_2>/<entity_lv_3>
And my rest controller have mapping /** for catch all of them.
I try make mapping with regexp:
#GetMapping(value = /{entityLv1}/{entityLv2:[a-z0-9_-]+/*})
But it not work fine, because server can't processed request with entity_lv_3 correctly.

Create one code client / flatten controllers with NSwag and AutoREST

I'm trying to create a code wrapper for an api with NSwag and Autorest.
Previously I was using Swashbuckle to generate the swagger file. It generated the swagger file with operationIds in the format actionMethod. This resulted in Autorest generating a code client that was 1-deep. All of the actions were on the top-level class.
For various reasons, I needed to change swagger generation to NSwag. This generates operationIds in the format controller_actionMethod. This results in AutoRest creating a composite class that exposes separate classes with actions for each controller.
How can either
Change how NSwag generates the operationIds
Change how Autorest maps operationIds
Note: I know I can manually change the swagger.json, but I'd like to keep a consistent automated process for generating the code client.
There doesn't appear to be any readily available settings, but you can hook into the generation process of NSwag
https://github.com/RicoSuter/NSwag/wiki/Document-Processors-and-Operation-Processors#operation-processors
The operation processor
class FlattenOperationsProcessor: IOperationProcessor
{
public async Task<bool> ProcessAsync(OperationProcessorContext context)
{
context.OperationDescription.Operation.OperationId = $"{context.MethodInfo.Name}";
return true;
}
}
Then add it in Startup.cs
document.OperationProcessors.Add(new FlattenOperationsProcessor());
Not sure if this was available when the question was asked, but here is a pretty easy way to do it:
services.AddSwaggerGen(c =>
{
...
c.CustomOperationIds(d => d.ActionDescriptor is ControllerActionDescriptor controllerActionDescriptor ? controllerActionDescriptor.MethodInfo.Name : d.ActionDescriptor.AttributeRouteInfo?.Name);
});
The same can also be set via c.SwaggerGeneratorOptions.OperationIdSelector
Note that ActionDescriptor.AttributeRouteInfo?.Name is the default I used from the source code here

How to have one single RESTier 0.6.0 service picking the database depending on the request?

Scenario A: Suppose you have several databases on the same SQL Server/SQL Azure instance sharing the exact same structure, where the database names are convention based, like db001, db002, ... and a single RESTier service must be able to address the correct database for each REST call, depending on some characteristic to be provided on the request header or on the URI path or query string.
Scenario B: A single RESTier service must be able to address more than one connection string, defined on the web.config file, depending on some characteristic to be provided on the request.
In both scenarios the base issue is the same, a single RESTier service to be able to address requests for more than one database, where the client must submit on each request a hint to the database to be used, a typical multitenant scenario. I'm using RESTier version 0.6 and the entity sets are automatically exposed from a Entity Framework model:
public class Entities : EntityFrameworkApi<SalesEntities> {
Question is, how would you advise to implement this kind of multi-tenant scenarios?
You could use a parameterized routePrefix like below and parse that part of the URL (HttpContext.Current.Request.RawUrl).
config.MapRestierRoute<Entities>("EntitiesApi", "api/{entitiesConfig}", new RestierBatchHandler(server));
Retrieve the correct connectionString from your Web.config and use that to create the DbContext:
Match match = Regex.Match(HttpContext.Current.Request.RawUrl, #"/api/(?<entitiesConfig>[A-Za-z0-9\-]+)/", RegexOptions.IgnoreCase);
string entitiesConfig = "DefaultEntitiesContext";
if (match.Success)
entitiesConfig = match.Groups["entitiesConfig"];
string connectionString = System.Configuration.ConfigurationManager.ConnectionStrings[entitiesConfig].ConnectionString;
var db = new SalesEntities(connectionString);
For your scenario, I think you will have two DbContext, each one connect to one DB instance, then will something like this will work for you?
In the configure method, we call MapRestierRoute twice, and each one will handle one DbContext with different route prefix, and when user initiate the request, the request URL will contain prefix and will auto route to related DB instance.
config.MapRestierRoute>( "TrippinApi", "api/TrippinA", new RestierBatchHandler(server));
config.MapRestierRoute>( "TrippinApi", "api/TrippinB", new RestierBatchHandler(server));
Let me if you have any issues with this.

How to implement a MetadataProvider that reads from database

I'm adding SSO support to a spring-based application using the spring-security-saml extension. The idea will be that an IDP can register to use SSO with my application by filling out a form in the UI, specifying their entityId, SSO authentication URL (for SP-initialized login), and public X.509 certificate. This seems to be a common workflow for SaaS applications with SSO support.
I haven't yet been able to find a clean way of implementing this with the spring saml extension, and am wondering if there is one. FilesystemMetadataProvider and HTTPMetadataProvider provide support for loading IDP metadata from an XML file or an HTTP GET, respectively, but I need to instead generate the IDP metadata from the above attributes that are stored in the database.
My current thinking is to use ResourceBackedMetadataProvider and use an implementation of Resource that fetches the metadata attributes from the database for each registered IDP. It would look something like:
class DatabaseBackedResource implements Resource {
MetadataDao metadataDao; // autowired
public InputStream getInputStream() throws ResourceException {
Collection<MetadataPojo> idpMetadata = metadataDao.getMetadata();
return convertMetadataPojosToInputStream(idpMetadata);
}
private InputStream convertMetadataPojosToInputStream(Collection<MetadataPojo> metadata) {
// somehow convert attributes to XMLObject
// then write XMLObject to input stream
// ...
}
// implementations of other methods
// ...
}
where MetadataPojo is simply a wrapper object of the above 3 attributes provided by an IDP. What I'm not sure about is how to generate a valid IDP metadata java object, given some attributes, using the spring saml extension. I see that AbstractMetadataProvider#unmarshallMetadata(InputStream) converts the metadata input stream into an XMLObject, but it is not clear to me how I will convert my collection of MetadataPojos into an XMLObject.
In short, is there a tool in the spring saml extension library to build an IDP metadata xml object given a list of string attributes? Or, taking a step back, is there a better way to implement a MetadataProvider that fetches the metadata information from a database instead of a file or url?
Update:
I implemented the above MetadataProvider implementation and Resource subclass and it's been working like a charm. To generate the IDP metadata documents I used various subclasses of AbstractSAMLObjectBuilder (i.e. EntityDescriptorBuilder, IDPSSODescriptorBuilder, KeyDescriptorBuilder, etc.) and that worked pretty cleanly. It would be nice if the Spring SAML library had an IDPMetadataGenerator class like the MetadataGenerator that exists for SP metadata.
If there was a cleaner way about this, I'd love to hear it.

OData - Data Service Simple Authentication

I would like to add simple authentication to Data Services, for now only to restrict access for particular applications by simple token.
I don't need Domain Authentication or Forms authentication.
I read a lot about authentication here:
http://franssenden.wordpress.com/2010/06/14/custom-security-odata-service-wcf-data-services/
http://mtaulty.com/CommunityServer/blogs/mike_taultys_blog/archive/2008/06/03/10482.aspx
http://mtaulty.com/CommunityServer/blogs/mike_taultys_blog/archive/2008/01/15/10119.aspx
http://mtaulty.com/CommunityServer/blogs/mike_taultys_blog/archive/2008/01/10/10100.aspx
Unfortunately it all demands a loooot of work.
Most of all creating custom IHttpModule.
There should be more simple solution.
I know that when I create object context on the client (WPF) I can add Credentials.
Uri uri = new Uri("http://localhost/myapp/odata.svc");
MyEntities ent= new MyEntities (uri);
ent.Credentials = new NetworkCredential("token", "zx5as9vxc5sa9h0vb6523cv56");
But where can I read them (without implementation of custom IHttpModule)?
I thought that I can use something in class that is implementation of Data Service for example:
protected override void OnStartProcessingRequest(ProcessRequestArgs args)
{
string cred = args.OperationContext.AbsoluteRequestUri.UserInfo;
}
I'm not familiar with UserInfo but description for it stands "Gets the user name, password, ...)
So I have two main questions:
Where can I read Credentials included by typing ent.Credentials = new NetworkCredential("token", "zx5as9vxc5sa9h0vb6523cv56");
Where can I (if I can) set UserInfo on the client app and use it in OnStartProcessingRequest method.
Regards,
Daniel SkowroĊ„ski
There's a series of post about authentication and WCF Data Services (which is the .NET implementation of the OData protocol): http://blogs.msdn.com/b/astoriateam/archive/tags/authentication/
You should be able to find lot more information there (including code samples).

Resources