I'm having a couple of issues with getting a correct WSDL generated for a ServiceStack SOAP+REST service.
The main issue is that when I use AddServiceReference the generated IOneWay is populated and the methods all return void. Looking at the provided SOAP examples it looks like ISyncReply should be populated (currently no operations at all) and the response type should be one of the fields in the DTO + Response object. What am I doing wrong?
The types and operations are distributed across multiple namespaces
but they are all referenced with a single ContractNamespace in AssemblyInfo
The DTO + Response naming convention has been followed
I thought it might be an issue with inherited Request/Response types, but even cutting them out completely doesn't change the situation, though apparently you can't inherit from a concrete type even from within a named namespace and have the operation parameters be generated properly
Using explicit [DataContract]/[DataMember] annotations does not make a difference
REST calls seem to be working as expected
I'm using the latest ServiceStack binaries
The WSDL does not have wsdl:output elements at all
Applies both SOAP 1.1 and SOAP 1.2 wsdls
And just to complicate the situation still further the metadata produced in http://*/metadata for each operation seems to be completely accurate!!
Let me know if there is any specific further information I can provide.
Related
What I intend to do: I'd like to use multiple ContentStores in the same system: one for freshly uploaded files (filesystem), one for (long term) archiving (AWS S3 or maybe GCS).
What I tried (and what actually does work):
Extended class File by another attribute private String contentStoreName;
Creating two ContentStores like described here: Spring-Content: Moving files from content store to another content store
Extending gettingstarted.FileContentController.setContent(Long, MultipartFile) by setting an identifier for the used ContentStore: f.get().setContentStoreName("regular");
Getting the content in dependence of the stored contentStoreName:
InputStream input;
if (Objects.equals(f.get().getContentStoreName(), "archive")) {
input = archiveContentStore.getContent(f.get());
} else {
input = regularContentStore.getContent(f.get());
}
Changing the contentStoreName when moving from one ContentStore to another:
Resource resource = regularContentStore.getResource(fileEntity.get());
archiveContentStore.setContent(fileEntity.get(), resource);
fileEntity.get().setContentStoreName("archive");
filesRepo.save(fileEntity.get());
The smell about this: Despite this code works, I guess it's not the intended way, because Spring-content usually does a lot with annotations and some magic in the background. But I can't find an annotation for an identifier / name for the ContentStore.
Question: Is there a more intended way of doing this in Spring-Content?
Beyond supporting multiple storage modules in a single application (via the FilesystemContentStore, et al annotations) Spring Content does not currently provide any logic for supporting classes of storage. That would be a layer that you need to create on top of Spring Content as you are starting to do.
In terms of Spring Content annotations it might be helpful for you to understand what modules manage what annotations.
Spring Content storage modules; FS, S3, etc all implement ContentStore and in doing so all provide management of the #ContentId and #ContentLength attributes (in addition to managing the actual content operations). Looks like you are using the ContentStore API (getContent/setContent) and therefore your entity's content id and length attributes will be managed for you.
Spring Content REST then provides management of #MimeType and #OriginalFileName attributes (in addition to providing comprehensive REST endpoints). My guess is that you are not using this and instead providing your own custom controller REST API that uses the 'contentStoreName' attribute to decide which store to put/get the content from. This approach seems fine.
That is all to say that a slightly more elegant approach, perhaps, that would allow you to use Spring Content REST might be to implement your own custom Archiving Storage module and encapsulate the "switching" logic you have above in its setContent/getContent/unsetContent methods. Note, this is actually quite easy (just 4 or 5 classes and I would point you at the GCP and Azure modules for inspiration). Note, that the REST API (for ContentStore) only calls those 3 APIs too so those are the only ones you would need to implement. This would mean you get to use Spring Content REST and all the features it provides; set of rest endpoints, byte range support and so on as well as encapsulating your "archiving" logic nicely.
I'm trying to add some forward compatibility to a Java application calling a Web Service at work, but JAXB seems to behave backward on the subject...
The application use the wsdl2java Maven plugin to generate a CXF Web Service client from a WSDL. It then uses that generated client to communicate with a Web Service (through SOAP over JMS).
When the Web Service sends an unknown element in its response to a call, JAXB fails with an "unexpected element" error, which is understandable, and XML-compliant. To be more forward compatible, I specified a custom jaxb-reader-validation-event-handler to ignore those specific errors, which solved the problem.
But while doing some complementary tests, I discovered non-XML-compliant behaviours.
First, JAXB doesn't care about elements' order, even inside a sequence, which is not XML-compliant, but good for forward compatibility, so why not.
However, it also doesn't care if a mandatory element (minOccurs="1") is not present, kindfully assigning it an arbitrary default value (which is, for elements bound to Java primitive values, their default values, like 0 for an int!).
This is both non-XML-compliant and not good for compatibility: if you need a mandatory, say, price as an integer, but the Web Service doesn't provide it for some reason, JAXB assigns the value 0 to it without a warning, making debugging really hard.
Apparently it's because if JAXB doesn't encounter an element, it simply doesn't call its setter, which means it will keep its default value.
[EDIT: I made some complementary tests, and when the application expect 1 element (maxOccurs="1") but the Web Service sends 2, JAXB calls the same setter two times, overriding the first value with the second, so it seems that once the client is generated from the WSDL, minOccurs and maxOccurs are simply ignored...]
How can I make JAXB to fail when a mandatory element is missing?
We noticed that, even for an element with minOccurs="1", the annotation of the corresponding generated attribute does not contain required = true. I tried to add it manually after the generation and before starting the application, but with no success: it seems it's simply ignored...
Maybe an additional JSR–303 validation covers what you want to achieve. You may either extend xjc’s behavior with a plugin like: https://github.com/krasa/krasa-jaxb-tools to have your binding classes annotated, or use Hibernate Validator in conjunction with XML validation config as described here: https://docs.jboss.org/hibernate/validator/4.1/reference/en-US/html/validator-xmlconfiguration.html#validator-xmlconfiguration
I have a repository class called FooRepository which has the ability to get various objects from a database.
I currently have one business object class called FooObject, which contains all the properties that I care about (Id, Name, CreatedDate, etc)... but my problem is that since ServiceStack only allows one DTO per route, I find myself unable to create more than one API method on my service to get back different types of data from my repository.
So, is it normal in ServiceStack to create a bunch of DTOs that simply return different types of data from the same repository? In ASP/MVC, this is rather easy because there's no route mapping clash going on, and I can simply create 'X' number of methods without the need to tie them to a specific DTO.
Thanks,
-Mario
Yes, each operation should have its own DTO. Keep in mind that the same DTO can be used for different HTTP methods(GET, PUT, POST, DELETE)
I am using ServiceStack and am having difficulty with one of my Request DTOs. One of the properties of type int is always coming through as 0 even though I can see it set correctly in the request.
Is there a method of debugging the ModelBinding process within ServiceStack?
I want to serialize an Entity Framework Self-Tracking Entities full object graph (parent + children in one to many relationships) into Json.
For serializing I use ServiceStack.JsonSerializer.
This is how my database looks like (for simplicity, I dropped all irrelevant fields):
I fetch a full profile graph in this way:
public Profile GetUserProfile(Guid userID)
{
using (var db = new AcmeEntities())
{
return db.Profiles.Include("ProfileImages").Single(p => p.UserId == userId);
}
}
The problem is that attempting to serialize it:
Profile profile = GetUserProfile(userId);
ServiceStack.JsonSerializer.SerializeToString(profile);
produces a StackOverflowException.
I believe that this is because EF provides an infinite model that screws the serializer up. That is, I can techincally call: profile.ProfileImages[0].Profile.ProfileImages[0].Profile ... and so on.
How can I "flatten" my EF object graph or otherwise prevent ServiceStack.JsonSerializer from running into stack overflow situation?
Note: I don't want to project my object into an anonymous type (like these suggestions) because that would introduce a very long and hard-to-maintain fragment of code).
You have conflicting concerns, the EF model is optimized for storing your data model in an RDBMS, and not for serialization - which is what role having separate DTOs would play. Otherwise your clients will be binded to your Database where every change on your data model has the potential to break your existing service clients.
With that said, the right thing to do would be to maintain separate DTOs that you map to which defines the desired shape (aka wireformat) that you want the models to look like from the outside world.
ServiceStack.Common includes built-in mapping functions (i.e. TranslateTo/PopulateFrom) that simplifies mapping entities to DTOs and vice-versa. Here's an example showing this:
https://groups.google.com/d/msg/servicestack/BF-egdVm3M8/0DXLIeDoVJEJ
The alternative is to decorate the fields you want to serialize on your Data Model with [DataContract] / [DataMember] fields. Any properties not attributed with [DataMember] wont be serialized - so you would use this to hide the cyclical references which are causing the StackOverflowException.
For the sake of my fellow StackOverflowers that get into this question, I'll explain what I eventually did:
In the case I described, you have to use the standard .NET serializer (rather than ServiceStack's): System.Web.Script.Serialization.JavaScriptSerializer. The reason is that you can decorate navigation properties you don't want the serializer to handle in a [ScriptIgnore] attribute.
By the way, you can still use ServiceStack.JsonSerializer for deserializing - it's faster than .NET's and you don't have the StackOverflowException issues I asked this question about.
The other problem is how to get the Self-Tracking Entities to decorate relevant navigation properties with [ScriptIgnore].
Explanation: Without [ScriptIgnore], serializing (using .NET Javascript serializer) will also raise an exception, about circular
references (similar to the issue that raises StackOverflowException in
ServiceStack). We need to eliminate the circularity, and this is done
using [ScriptIgnore].
So I edited the .TT file that came with ADO.NET Self-Tracking Entity Generator Template and set it to contain [ScriptIgnore] in relevant places (if someone will want the code diff, write me a comment). Some say that it's a bad practice to edit these "external", not-meant-to-be-edited files, but heck - it solves the problem, and it's the only way that doesn't force me to re-architect my whole application (use POCOs instead of STEs, use DTOs for everything etc.)
#mythz: I don't absolutely agree with your argue about using DTOs - see me comments to your answer. I really appreciate your enormous efforts building ServiceStack (all of the modules!) and making it free to use and open-source. I just encourage you to either respect [ScriptIgnore] attribute in your text serializers or come up with an attribute of yours. Else, even if one actually can use DTOs, they can't add navigation properties from a child object back to a parent one because they'll get a StackOverflowException.
I do mark your answer as "accepted" because after all, it helped me finding my way in this issue.
Be sure to Detach entity from ObjectContext before Serializing it.
I also used Newton JsonSerializer.
JsonConvert.SerializeObject(EntityObject, Formatting.Indented, new JsonSerializerSettings { PreserveReferencesHandling = PreserveReferencesHandling.Objects });