camel-users mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Matt Sicker <boa...@gmail.com>
Subject Re: Is it possible to make a message header or property immutable?
Date Wed, 06 Jul 2016 17:03:05 GMT
I have plenty of endpoints based on POST/PUT where the message body already
contains important information, so I've been using headers or properties to
add information without needing to make the body itself a map or some other
wrapper. If this isn't the proper way to use camel, then I'd like to hear
about it because sometimes I feel like I'm missing something here. The DSL
certainly makes it easier to manipulate headers and properties than it does
the body.

On 6 July 2016 at 10:03, Brad Johnson <brad.johnson@mediadriver.com> wrote:

> 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 <boards@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.johnson@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 <boards@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 <boards@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.rashti@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+s465427n5784811h4@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+s465427n465428h31@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 <boards@gmail.com>
> > > > >
> > > >
> > > >
> > > >
> > > > --
> > > > Matt Sicker <boards@gmail.com>
> > > >
> > >
> >
> >
> >
> > --
> > Matt Sicker <boards@gmail.com>
> >
>



-- 
Matt Sicker <boards@gmail.com>

Mime
  • Unnamed multipart/alternative (inline, None, 0 bytes)
View raw message