In our BizTalk application we would like all internal messages to have the same structure, with a Header element with routing and logging information (this header is the same for all messages), all properties of which are promoted, and a Body element which is different for each specific message. When I create a new message based on the above (by setting the schema's DataStructure or BaseType), I would like the promotions to be kept as well.
I tried getting this to work by creating a Header message with the required fields and promotions, and also by creating a "complete" BaseMessage with a Header and Body element (again with all properties in the header promoted), but either way in a schema using this DataStructure the property promotions are not kept (which I guess makes sense; the XPaths indicated in the PropertySchema are different, because the BaseMessage namespace is different from the derived message).
Is there a way to have a shared schema including property promotions? Or can you copy the structure in a derived message, but you always have to redo the promotions?
Thanks for any insights!
We have a similar header structure that is imported and always have to redo the promotions.
My recommendation would be to solve this problem by not doing what you're describing. While it sounds good in theory, you will find eventually that it's over-engineering with little practical benefit.
What will matter is the routing information, meaning, the Properties, not the Header section. So, it's fine to have shared Property Schemas (deployed separately) but don't try to shoehorn the messages into a 'common' wrapper.
Related
I have a resource, as an example a 'book'.
I want to create a REST POST endpoint to allow consumers to create a new book.
However, some of the properties are required and computed by API, and others were actually taken as they are
Book
{
name,
color,
author # computed
}
Let's say the author is somehow calculated in API based on the book name.
I can think of these solutions each has its drawbacks:
enforce consumer to provide the author and just filter it (do not take into account as an input) # bad because it is very unpredictable why the author was changed
allow the user to provide author # same problem
do not allow the user to provide an author and show an exception if the user provides it
The last solution seems to be the most obvious one. The main problem I can see is that it is inconsistent and can be bizarre for consumers to see the author later on GET request.
I want my POST endpoint to be as expressive as possible. So the POST and GET data transfer objects will look almost the same.
Are there any simple, expressive, and predictable patterns to consider?
Personally I'm a big fan of using the same format for a GET request as well as a PUT.
This makes it possible for a client to do a GET request, add a property to the object they received and immediately PUT again. If your API and clients follow this pattern, it also means it can easily add new properties to GET requests and not break clients.
However, while this is a nice pattern I don't really think that same expectation exists at much for 'creation'. There's usually many things that make less less to require as a property when creating new items (think 'id' for example), so I usually:
Define a schema for PUT and GET.
Define a separate schema for POST that only contains the relevant properties for creation.
If users supply properties not in the schema, always error with a 422.
some of the properties are required and computed by API
Computed properties are neither required nor optional, by definition. No reason to ask consumers to pass such properties.
do not allow the user to provide an author and show an exception if the user provides it
Indeed, DTO should not contain author-property. Consumers can send over network whatever they want, however it is the responsibility of the API-provider to publish contract (DTO) for consumers to use properly. API-provider controls over what properties to consider, and no exception should be thrown, as the number of "bad" properties that can be sent by consumers is endless.
So the POST and GET data transfer objects will look almost the same
Making DTOs of the same resource look the same is not a goal. In many cases, get-operation exposes a lot more properties than post-operation for the same resource, especially when designing domain-driven APIs.
Are there any simple, expressive, and predictable patterns to consider?
If you want your API to express the fact that author is computed, you can have the following endpoints:
POST http://.../author-computed-books
GET http://.../books/1
Personally, I wouldn't implement that way since it does not look natural, however you can get the idea.
I want my POST endpoint to be as expressive as possible. So the POST
and GET data transfer objects will look almost the same.
Maybe just document it instead of relying explicit stuff like it must be almost the same as the GET endpoint.
E.g. my POST endpoint is POST /number "1011" and my GET endpoint is GET /number -> 11. If I don't document that I expect binary and I serve decimal, then nobody will know and they would guess for example decimal for both. Beyond documentation another way of doing this and to be more explicit is changing the response for GET to include the base {"base":10, value:"11"} or changing the GET endpoint GET /number/decimal -> 11.
As of the computed author I don't understand how you would compute it. I mean either a book is registered and the consumer shouldn't register it again or you don't know much about the author of it. If the latter, then you can guess e.g. based on google results for the title, but it will be a guess, not necessarily true. The same with consumer data, but at least that is what the consumers provided. There is no certainty. So for me it would be a complex property not just a primitive one if the source of the information matters. Something like "author": {name: "John Wayne", "source": "consumer/service"} normally it is complex too, because authors tend to have ids, names, other books, etc.
Another thought that if it is weird for the consumers instead of expected, then I have no idea why it is a feature at all. If author guessing is a service, then a possible solution is making the property mandatory and adding a guessing service GET /author?by-book-name={book-name}, so they can use the service if they want to. Or the same with a completely optional property. This way you give back the control to the consumers on whether they want to use this service or not.
I'm about to begin writing a suite of WCF services for a variety of business applications. This SOA will be very immature to begin with and eventually evolve into a strong middle-ware layer.
Unfortunately I do not have the luxury of writing a full set of services and then re-factoring applications to use them, it will be a iterative process done over time. The question I have is around evolving (changing, adding, removing properties) business objects.
For example: If you have a SOA exposing a service that returns obj1. That service is being consumed by app1, app2, app3. Imagine that object is changed for app1, I don't want to have to update app2 and app3 for changes made for app1. If the change is an add property it will work fine, it will simply not be mapped but what happens when you remove a property? Or change a property from a string to an int? How do you manage the change?
Thanks in advance for you help?
PS: I did do a little picture but apparently I need a reputation of 10 so you will have to use your imagination...
The goal is to limit the changes you force your clients to have to make immediately. They may eventually have to make some changes, but hopefully it is only under unavoidable circumstances like they are multiple versions behind and you are phasing it out altogether.
Non-breaking changes can be:
Adding optional properties
Adding new operations
Breaking changes include:
Adding required properties
Removing properties
Changing data types of properties
Changing name of properties
Removing operations
Renaming operations
Changing the order of the properties if explicitly specified
Changing bindings
Changing service namespace
Changing the meaning of the operation. What I mean by this, for example, is if the operation always returned all records but it was changed to only return certain records. This would break the clients expected response.
Options:
Add a new operation to handle the updated properties and logic. Modify code behind original operation to set new properties and refactor service logic if you can. Just remember to not change the meaning of the operation.
If you are wanting to remove an operation that you no longer want to support. You are forcing the client to have to change at some point. You could add documentation in the wsdl to let client know that it is being deprecated. If you are letting the client use your contract dll you could use the [Obsolete] attribute (it is not generated in final wsdl so that's why you can't just use it for all)
If it is a big change altogether, a new version of the service and/or interface and endpoint can be created easily. Ie v2, v3, etc. Then you can have the clients upgrade to the new version when the time is right
Here is also a good flowchart from “Apress - Pro WCF4: Practical Microsoft SOA Implementation” that may help.
I'm having some message design head-aches. I want to start up an NServiceBus saga for a long running process. Part of the data needed to do the initialization is a list of constraints, which are implementations of an abstract base class. As I've understood the design philosophy, messages should ideally be
Self-contained, that is contain all the data needed to process them. Following this, I would pass along all the list of constraints in the message.
Versionable. NServiceBus does this by using an XML serializer which does not pass along type information (see this thread answer by Udi). In my case, that means I cannot on the recieving end pick up the specifics of the constraints.
The serialization problems can be "solved" by using the BinarySerializer, but this does not seem to be a recommended practice since it breaks versioning. The alternative is to send along some identifier so that the constraints can be retrieved from some datastore, but that would remove the "self-containedness".
Is there a third way here, or do I simply have to choose some "least bad" solution?
There is also the option of having these objects injected into your saga via DI.
Just create a boostrapping class that at startup will call:
Configure.Instance.Configurer.ConfigureProperty<yourSaga>(s => s.SomeProperty = value);
Hope developers team wouldn't miss my message. NullValueHandling must be an optional parameter for the JsonFormatter attribute because there are a lot of cases when properties of the object required on client side independently of their value.
And I personally got some troubles trying to identify why my object doesn't have half of it properties.
By the way limitation for DbConext and entity namespace to make the entity observerable on client side is not good too.
Thanks.
Breeze currently sets NullValueHandling to 'Ignore', so as to minimize payloads by not sending any 'null' values. We did not think that this would be an issue because the json serialized objects are materialized into 'breeze' entities on the client and breeze has metadata to determine what the valid properties for each entity are.
What is the use case for actually sending 'nulls' to the client? This is an relatively easy enhancement to make if we have a good use case. The only one that comes to mind is with anonymous objects queried from the server for which metadata will not exist. Is this what you are encountering?
I am new to programming (6 weeks now). i am reading a lot of books, sites and blogs right now and i learn something new every day.
Right now i am using coldfusion (job). I have read many of the oop and cf related articles on the web and i am planning to get into mxunit next and after that to look at some frameworks.
One thing bothers me and i am not able to find a satisfactory answer. Beans are sometimes described as DataTransferObjects, they hold Data from one or many sources.
What is the recommended practice to handle this data?
Should i use a separate Object that reads the data, mutates it and than writes it back to the bean, so that the bean is just a storage for data (accessible through getters) or should i implement the methods to manipulate the data in the bean.
I see two options.
1. The bean is only storage, other objects have to do something with its data.
2. The bean is storage and logic, other objects tell it to do something with its data.
The second option seems to me to adhere more to encapsulation while the first seems to be the way that beans are used.
I am sure both options fit someones need and are recommended in a specific context but what is recommended in general, especially when someone does not know enough about the greater application picture and is a beginner?
Example:
I have created a bean that holds an Item from a database with the item id, a name, and an 1d-array. Every array element is a struct that holds a user with its id, its name and its amount of the item. Through a getter i output the data in a table in which i can also change the amount for each user or check a user for deletion from this item.
Where do i put the logic to handle the application users input?
Do i tell the bean to change its array according to the user input?
Or do i create an object that changes the array and writes that new array into the bean?
(All database access (CreateReadUpdateDelete) is handled through a DataAccessObject that gets the bean as an argument. The DAO also contains a gateway method to read more than one record from the database. I use this method to get a table of items, which i can click to create the bean and its data.)
You're observing something known as "anemic domain model". Yes, it's very common, and no, it's not good OO design. Generally, logic should be with the data it operates on.
However, there's also the matter of separation of concerns - you don't want to stuff everything into the domain model. For example, database access is often considered a technically separate layer and not something the domain models themselves should be doing - it seems you already have that separated. What exactly should and should not be part of the domain model depends on the concrete case - good design can't really be expressed in absolute rules.
Another concern is models that get transferred over the network, e.g. between an app server and a web frontend. You want these to contain only the data itself to reduce badnwidth usage and latency. But that doesn't mean they can't contain logic, since methods are not part of the serialized objects. Derived fields and caches are - but they can usually be marked as transient in some way so that they are not transferred.
Your bean should contain both your data and logic.
Data Transfer Objects are used to transfer objects over the network, such as from ColdFusion to a Flex application in the browser. DTOs only contain relevant fields of an object's data.
Where possible you should try to minimise exposing the internal implementation of your bean, (such as the array of user structs) to other objects. To change the array you should just call mutator functions directly on your bean, such as yourBean.addUser(user) which appends the user struct to the internal array.
No need to create a separate DAO with a composed Gateway object for your data access. Just put all of your database access methods (CRUD plus table queries) into a single Gateway object.