问题
BACKGROUND
Assume you have a (SOAP) web service, BookService
, managing books in a library. In the information model assume that the Book
entity has the following attributes:
id
author
publisher
title
shelfId
In order to manipulate the data four web service operations are defined:
AddBook
GetBook
UpdateBook
DeleteBook
Request and response message are defined for each operation. However, the design of the update message XML schemas is more complicated. We would like to achieve the following qualities:
- R1: Possibility to reset/delete previous values of an attribute. E.g. say that you no more will keep the book in the library and thereby would like to reset/empty/remove the attribute value of the attribute
shelfId
for that specific book. - R2: Avoid chattiness in the web services. See the anti-pattern Chatty Services.
- R3: Prepare for future requirements on Concurrency Control and Optimistic Locking. We may want to minimize (or remove) the risk of having updates made on based of old information.
DESIGN ALTERNATIVES
I see three mayor alternatives, of which one has several sub-options, to design the update message(s):
- Send the entire business document. Left-out elements (having
minOccurs="0"
in the schema) OR elements explicitly set to null, i.e.<shelfId xsi:nil="true"/>
, would be interpreted as deletion of the previous values. - Highlight the changes or send only the diff.
- Send the entire business document, but mark the modified elements using an attribute specific to this purpose. Example:
<author dirty="true">Hemingway<author/>
. The provider of the service then updates only those elements marked as dirty and ignores the other ones. - In the message schema, set all elements, but the identifier
id
, to haveminOccurs="0"
. The consumer sends only those elements which are to be modified. A left-out element must not semantically be interpreted as a deletion. In order to delete a value the explicit XMLNULL
value must be used. Example:<shelfId xsi:nil="true"/>
. - Send the entire business document, but also submit a copy of the previously read document. The provider can then compare the two documents and update only those attributes for which the new and the previous documents differ.
- Send the entire business document, but mark the modified elements using an attribute specific to this purpose. Example:
- Define multiple operations. Instead of only using one operation,
UpdateBook
, define multiple operation based on which elements you believe will have to be updated, e.g.UpdateBookAuthor
,UpdateBookPublisher
and so on. Each of these will have only mandatory elements and for removal of elements use the explicit NULL of XML, e.g.<shelfId xsi:nil="true"/>
.
DISCUSSION
Alt 3 has the advantage of being simple to understand, but the drawback is that consumers would need to invoke multiple operations in case multiple fields in the Book
entity should be updated. This makes the service "chatty" (see R3 above), giving performance penalties.
Alt 2 is more complex than Alt 1, but there are some advantages of Alt 2 related to Optimistic Concurrency Control:
- For situations when optimistic locking with timestamps/versions for each field is stored in the database (e.g.
authorVersion
) => Alt 2 provides a way of letting multiple users modify different parts, such asauthor
andpublisher
, of the sameBook
concurrently with less risk of having faults. - For situations when optimistic locking with one single timestamp/version for the entire
Book
is stored in the database => No real advantage of Alt 2 over Alt 1. Even if an update only modifies one field, a too old version number of the request would result in a fault. - For situations when no concurrency control or optimistic/pessimistic locking is used => Alt 2 gives less risk than Alt 1 of overwriting with old data, but still other inconsistent changes may give problems.
There is yet another situation in which Alt 2 (and Alt 3) gives an advantage over Alt 1. The consumer may not store all the data about the Book
entity. For example, a robot picking the books from their shelf's may be programmed more effectively if it doesn't need to keep track (cache) on the information on the author, but just the shelf, when updating the shelf information.
An advantage of the approach in Alt 2.3, where the consumer submits entire copies of previous versions instead of version numbers or timestamps, is that no dedicated column in the database is needed for version number or timestamp.
To sum it up I would say Alt 2.2 looks like the most attractive one for most cases. The challenge here is just that the frameworks deserializing the XML must be able to distinguish a left-out element from an element explicitly set to NULL, e.g. <shelfId xsi:nil="true"/>
. See a post on this topic here.
QUESTION
Which of the alternatives would you go for? Do you see other, better alternatives? What do you think of the discussion?
回答1:
As you have already discussed, alt 2.2 seems to be rather feasible. However, the distinction between minoccurs=0 and nil is often ignored by frameworks and is also hard to understand for many users (potentially of this interface). Thus I would go for a variation, where in one change message you mark with every attribute explicitly when you want them to be nullified.
etag could be one standard to be used for optimistic locking. I think you have discussed the implications of locking mechanisms already extensively. It should work the way you describe.
Alt 1 is a lot simpler, both in message design and usage/implementation and if traffic is not an issue and optimistic locking for whole objects is enough (which is most often the case imho), that could also work well.
You should also take into account that with some business processes, changes of different attributes are interdependent so it doesn't make sense to have separate versioning for attributes, since a change at one attribute can be wrong even if only another attribute was outdated at the time of change.
If this can be the case, it is another reason for alt 1.
来源:https://stackoverflow.com/questions/8709715/how-to-use-optional-attributes-in-web-service-update-messages-dtos