camel-users mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Brad Johnson <brad.john...@mediadriver.com>
Subject Re: Is it possible to make a message header or property immutable?
Date Wed, 06 Jul 2016 15:03:26 GMT
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>
>

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