But if you are using CXFRS then you can make the databean itself contain what I'll call initializable data. This isn't a bad example but you get the idea.
public void setFirstName(String firstName) { if(this.firstName==null) this.firstName=firstName; //Maybe throw an exception if it is already set. } So the first time that data can be set but after that it is immutable. Since the path query params are items you can access via the annotations you can use them to do the initial setting on the data. Part of this, from my perspective, is that when I move from REST to Java objects I almost always want that query data in my data objects themselves. If I'm updating a contact by first name (can't imagine that ever being a use case so SSN was probably a better choice) then the firstName query parameter is probably something I'm going to set on my Contact data object. Or worst case the path and the data object will both have that data. After that all my routing is based on the Contact object and other logical concerns and not on REST or SOAP or other header information that I haven't already tucked inside the data object. I believe one can also specify that JAXB set the data by fields during marshaling/unmarshaling. And then the setters for some of the critical fields can actually be no-ops or throw exceptions. None of that may be pertinent to the REST DSL however as I don't use it or know it. But I almost never exclusively program REST only APIs and so the solutions I use in Camel can't count on or use REST only mechanics. In a way I think that's an abstraction leak. The HTTP verbs, query params, and so on shouldn't make it past the endpoint. None of the routing or logic should care whether the data came from REST, SOAP, JMS or wherever. And certainly if you us an immutable bean in the header it could be replaced by a gremlin programmer. But if that bean has no functional purpose other than to do sanity checking to ensure that the headers haven't been mutated then nobody would really have any reason to ever do that. And if you wanted to carry it one step further you could have that immutable object generate a UUID and put that in a correlationID header that you could use to verify that that the immutable bean hadn't been replaced. If it had the ID wouldn't match up. So that correlationID and immutable bean wouldn't have any functional purpose that a developer would ever use them for except in ones unit tests and perhaps at the end of the routes to verify that everything went right. I've also found in these situations that I make sure I'm on top of the routing and the one who is writing all that code as a crosscutting concern to all the projects so that if the developers mess with data they shouldn't and that will change the routing then it will end up breaking hard. On Tue, Jul 5, 2016 at 6:36 PM, Matt Sicker <boa...@gmail.com> wrote: > I actually used to use CXFRS in this application (you can still see > remnants of it like using the header "operationName" to route from a REST > endpoint to an ActiveMQ queue). Even if I used an immutable bean in the > header, that bean could still be replaced. It seems like the only way to > implement a truly immutable header or property would be an addition to the > camel-core API, and I'm not so sure if such a feature would be accepted. > > On 5 July 2016 at 18:20, Brad Johnson <brad.john...@mediadriver.com> > wrote: > > > I've always used CXFRS so don't have any experience with the REST DSL > > itself. With CXFRS I usually end up binding everything to the data object > > when it first comes in and that does remain immutable so I don't end up > > working with headers for any data elements. By using the same interface > for > > both my SOAP and REST and binding it this way. The only requirement then > > is that the data bean have @XmlRootElement specified so that JAXB knows > how > > to handle it. For the routing I then use the recipientList along with the > > method name so that it is disconnected from either SOAP or REST. I'm > > making this example up off the top of my head so don't hold me to the > > specifics. > > > > @WebMethod(operationName = "updateContact", action = "") > > @WebResult(name = "Contact", targetNamespace = "") > > @PUT > > @Produces({MediaType.APPLICATION_JSON,MediaType.APPLICATION_XML}) > > @Consumes({MediaType.APPLICATION_JSON,MediaType.APPLICATION_XML}) > > @Path("contact/{firstName}") > > public Contact updateContact(Contact contact) { > > ... > > } > > > > Then in the CXF blueprint file I'll put something like this: > > > > <recipientList> > > <simple>direct-vm:${header.operationName}</simple> > > </recipientList> > > > > > > In this case when that interface is invoked it equates to the defined > > "operationName" on a direct-VM but that could be any transport. > > > > So calling that method invokes direct-vm:updateContact and that's where I > > start the route handling. But by that time the data is firmly bound to > the > > bean and is not mutable. > > > > But you could, at the very least, create wrapper class with immutable > > fields on it that you could instantiate and save in the header as the > first > > step in the process. That would prevent any modification of those > > variables and at least help in debugging when something goes wrong. Why > > didn't this go where it was supposed to? Catch the exception and then > pull > > the original bean with immutable fields and see what it says the values > > should be compared to what they currently are. > > > > It sounds like this is going to be a case where you're going to have to > > rely on some fairly rigorous testing to make sure nobody is doing > anything > > stoopid. > > > > > > On Tue, Jul 5, 2016 at 4:03 PM, Matt Sicker <boa...@gmail.com> wrote: > > > > > Let me give a more specific use case. Path parameters from rest-dsl are > > > passed in as message headers. I don't want any route to accidentally > > > overwrite or modify those headers as they're useful for the entire > > > lifecycle of that message. > > > > > > On 5 July 2016 at 16:00, Matt Sicker <boa...@gmail.com> wrote: > > > > > > > The exact use case is preventing developers from [inadvertently] > > > modifying > > > > headers or properties that are used before and after a particular > > > subroute. > > > > > > > > On 5 July 2016 at 15:57, souciance <souciance.eqdam.ras...@gmail.com > > > > > > wrote: > > > > > > > >> I guess the question is, why would different routes split over > > different > > > >> bundles want to write over the same header/property? What's the case > > > here? > > > >> Surely it cannot be just to prevent accidents by developers because > > what > > > >> would be their reason to write over that header? > > > >> > > > >> I think it is better to agree on a naming and some sort of other > > > >> convention > > > >> and stick to that because I don't think there is a way to to make a > > > header > > > >> immutable. I guess an ugly solution would be to save the header in a > > map > > > >> and give the key name something very unique. > > > >> > > > >> On Tue, Jul 5, 2016 at 10:48 PM, Matt Sicker [via Camel] < > > > >> ml-node+s465427n578481...@n5.nabble.com> wrote: > > > >> > > > >> > Please let me know if you think of anything! > > > >> > > > > >> > On 5 July 2016 at 15:16, Brad Johnson <[hidden email] > > > >> > <http:///user/SendEmail.jtp?type=node&node=5784811&i=0>> wrote: > > > >> > > > > >> > > I certainly understand the impulse and think it is spot on but > > can't > > > >> > think > > > >> > > of how to do it with headers. Claim checks might work but they > > are > > > >> > really > > > >> > > for reducing overhead of data and not for locking like that but > > that > > > >> > might > > > >> > > be a viable solution depending on the exact problem. > > > >> > > > > > >> > > Thanks Matt, this is going to be stuck in my head now. I'll > > > probably > > > >> > dream > > > >> > > of an answer of some sort tonight. > > > >> > > > > > >> > > Brad > > > >> > > > > > >> > > On Tue, Jul 5, 2016 at 3:02 PM, Matt Sicker <[hidden email] > > > >> > <http:///user/SendEmail.jtp?type=node&node=5784811&i=1>> wrote: > > > >> > > > > > >> > > > My use case is basically to help prevent bugs where a header > or > > > >> > exchange > > > >> > > > property gets modified. Some of my routes in question branch > out > > > >> into > > > >> > > > several different bundles, and it is difficult to enforce > > > contracts > > > >> > that > > > >> > > > way amongst several developers with varying levels of Camel > > > >> expertise. > > > >> > > > Similar to how one might use final variables to prevent people > > > from > > > >> > > > reassigning them, this could be a final header that prevents > > > people > > > >> > from > > > >> > > > reusing them for things. > > > >> > > > > > > >> > > > On 5 July 2016 at 14:22, Brad Johnson <[hidden email] > > > >> > <http:///user/SendEmail.jtp?type=node&node=5784811&i=2>> > > > >> > > > wrote: > > > >> > > > > > > >> > > > > That's what I figured. I'd have to look at the Map > > > implementation > > > >> > of > > > >> > > the > > > >> > > > > exchange but as far as I know there isn't a way to make it a > > > write > > > >> > once > > > >> > > > > only operation. It's just a map of some sort. There might > > be a > > > >> way > > > >> > to > > > >> > > > do > > > >> > > > > it with transactions but I'm not an expert there. I > generally > > > use > > > >> > > > headers > > > >> > > > > but in reality should probably be using exchange properties > > more > > > >> > often. > > > >> > > > > > > > >> > > > > > > > >> > > > > > > > >> > > > > > > >> > > > > > >> > > > > >> > > > > > > http://stackoverflow.com/questions/10330998/passing-values-between-processors-in-apache-camel > > > >> > > > > > > > >> > > > > Almost any mechanism I can think of off the top of my head > > could > > > >> be > > > >> > > > > subverted by someone who wanted to or who didn't understand > > that > > > >> the > > > >> > > > value > > > >> > > > > associated with the bean shouldn't be modified. For > example, > > > you > > > >> > could > > > >> > > > > create a bean that you associate with your header that > stores > > > data > > > >> > but > > > >> > > > also > > > >> > > > > returns a UUID. That UUID could be stored in another header > > and > > > >> > > sometime > > > >> > > > > later in the routes you could verify that the bean stored > > under > > > >> your > > > >> > > key > > > >> > > > > returns the same UUID as the header indicates. But that > > > wouldn't > > > >> > stop > > > >> > > > > someone from changing the bean stored to the key and it > > wouldn't > > > >> > > prevent > > > >> > > > > them from updating the UUID to a new bean they might create. > > > >> > > > > > > > >> > > > > On Tue, Jul 5, 2016 at 1:49 PM, Matt Sicker <[hidden email] > > > >> > <http:///user/SendEmail.jtp?type=node&node=5784811&i=3>> wrote: > > > >> > > > > > > > >> > > > > > I'm thinking of an idea to prevent a header from being > > > modified > > > >> by > > > >> > > > other > > > >> > > > > > parts of the route. A sort of contract if you will. > > > >> > > > > > > > > >> > > > > > On 5 July 2016 at 13:01, Brad Johnson <[hidden email] > > > >> > <http:///user/SendEmail.jtp?type=node&node=5784811&i=4>> > > > >> > > > > > wrote: > > > >> > > > > > > > > >> > > > > > > Is there another part of your process that is > specifically > > > >> > changing > > > >> > > > the > > > >> > > > > > > header or are you more concerned about it being > > consistently > > > >> > there > > > >> > > > > across > > > >> > > > > > > routes? Nothing will change it automatically if it is > > your > > > >> > header. > > > >> > > > I > > > >> > > > > > > don't remember the actual implementation but > conceptually > > it > > > >> is > > > >> > > just > > > >> > > > a > > > >> > > > > > > hastable/map with key/values. If you set header with > some > > > >> > specific > > > >> > > > key > > > >> > > > > > > then nothing else will change it. > > > >> > > > > > > > > > >> > > > > > > As an example, I use a camel splitter and then set a > > header > > > >> with > > > >> > > the > > > >> > > > > > > splitter index so that I can use it in another route > later > > > to > > > >> > > > > reassemble > > > >> > > > > > > with the resequencer. > > > >> > > > > > > > > > >> > > > > > > <split> > > > >> > > > > > > <simple>${body}</simple> > > > >> > > > > > > <setHeader headerName="seqnum"> > > > >> > > > > > > <simple>exchangeProperty.CamelSplitIndex</simple> > > > >> > > > > > > </setHeader> > > > >> > > > > > > ... > > > >> > > > > > > > > > >> > > > > > > The "seqnum" is just a key that I'm defining. I could > > > >> obviously > > > >> > > call > > > >> > > > > it > > > >> > > > > > > anything "sequenceNumber" or whatever but when I access > it > > > >> later > > > >> > > that > > > >> > > > > > > header is available on the exchange. If I explicitly > > change > > > >> what > > > >> > > the > > > >> > > > > map > > > >> > > > > > is > > > >> > > > > > > storing for "seqnum" then it will be different because I > > > can't > > > >> > make > > > >> > > > the > > > >> > > > > > > header map itself immutable. > > > >> > > > > > > > > > >> > > > > > > > > > >> > > > > > > On Tue, Jul 5, 2016 at 10:33 AM, Matt Sicker <[hidden > > email] > > > >> > <http:///user/SendEmail.jtp?type=node&node=5784811&i=5>> > > > >> > > > wrote: > > > >> > > > > > > > > > >> > > > > > > > As in once I set the header, nothing can change the > > header > > > >> > during > > > >> > > > the > > > >> > > > > > > > lifecycle of the message during a route. Same for an > > > >> exchange > > > >> > > > > property. > > > >> > > > > > > > > > > >> > > > > > > > -- > > > >> > > > > > > > Matt Sicker <[hidden email] > > > >> > <http:///user/SendEmail.jtp?type=node&node=5784811&i=6>> > > > >> > > > > > > > > > > >> > > > > > > > > > >> > > > > > > > > >> > > > > > > > > >> > > > > > > > > >> > > > > > -- > > > >> > > > > > Matt Sicker <[hidden email] > > > >> > <http:///user/SendEmail.jtp?type=node&node=5784811&i=7>> > > > >> > > > > > > > > >> > > > > > > > >> > > > > > > >> > > > > > > >> > > > > > > >> > > > -- > > > >> > > > Matt Sicker <[hidden email] > > > >> > <http:///user/SendEmail.jtp?type=node&node=5784811&i=8>> > > > >> > > > > > > >> > > > > > >> > > > > >> > > > > >> > > > > >> > -- > > > >> > Matt Sicker <[hidden email] > > > >> > <http:///user/SendEmail.jtp?type=node&node=5784811&i=9>> > > > >> > > > > >> > > > > >> > ------------------------------ > > > >> > If you reply to this email, your message will be added to the > > > discussion > > > >> > below: > > > >> > > > > >> > > > > >> > > > > > > http://camel.465427.n5.nabble.com/Is-it-possible-to-make-a-message-header-or-property-immutable-tp5784800p5784811.html > > > >> > To start a new topic under Camel - Users, email > > > >> > ml-node+s465427n465428...@n5.nabble.com > > > >> > To unsubscribe from Camel - Users, click here > > > >> > < > > > >> > > > > > > http://camel.465427.n5.nabble.com/template/NamlServlet.jtp?macro=unsubscribe_by_code&node=465428&code=c291Y2lhbmNlLmVxZGFtLnJhc2h0aUBnbWFpbC5jb218NDY1NDI4fDE1MzI5MTE2NTY= > > > >> > > > > >> > . > > > >> > NAML > > > >> > < > > > >> > > > > > > http://camel.465427.n5.nabble.com/template/NamlServlet.jtp?macro=macro_viewer&id=instant_html%21nabble%3Aemail.naml&base=nabble.naml.namespaces.BasicNamespace-nabble.view.web.template.NabbleNamespace-nabble.view.web.template.NodeNamespace&breadcrumbs=notify_subscribers%21nabble%3Aemail.naml-instant_emails%21nabble%3Aemail.naml-send_instant_email%21nabble%3Aemail.naml > > > >> > > > > >> > > > > >> > > > >> > > > >> > > > >> > > > >> -- > > > >> View this message in context: > > > >> > > > > > > http://camel.465427.n5.nabble.com/Is-it-possible-to-make-a-message-header-or-property-immutable-tp5784800p5784812.html > > > >> Sent from the Camel - Users mailing list archive at Nabble.com. > > > > > > > > > > > > > > > > > > > > -- > > > > Matt Sicker <boa...@gmail.com> > > > > > > > > > > > > > > > > -- > > > Matt Sicker <boa...@gmail.com> > > > > > > > > > -- > Matt Sicker <boa...@gmail.com> >