You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@activemq.apache.org by Jakub Korab <ja...@gmail.com> on 2015/03/13 17:13:20 UTC
ActiveMQ DSLs
Hi All,
In working on a separate project, I found the need to instantiate
multiple different ActiveMQ configurations. Rather than writing up a lot
of different XML configs or messing around with assembling BrokerService
instances, I wrote a DSL that mimics the ActiveMQ config schema via a
directed builder pattern, much like Camel. Here's an example:
BrokerContext context = new
BrokerContext(ActiveMQBrokers.broker("embeddedBroker").useJmx(false).persistent(false)
.transportConnectors()
.transportConnector("openwire", "tcp://0.0.0.0:61616").end()
.end()
.plugins()
.simpleAuthenticationPlugin()
.users()
.authenticationUser("user").password("pass").groups("guests").end()
.end()
.end()
.end()));
context.start();
...
context.end();
Unlike Camel, the DSL itself defines a model that is used to instantiate
a BrokerService. Camel has an intermediate set of VOs
(org.apache.camel.model) between the Java DSL and the implementation. I
had a go at generating a similar model via JAXB from the ActiveMQ
schema, to abstract away the DSL/XBean config, but the generated classes
were hideous and I abandoned the approach.
I also developed a testing DSL for JUnit that allows you to spin up
these configurations, and rely on the JUnit runner to start up and shut
down the broker. The test DSL also allows for the definition of proxies
(using the ActiveMQ SocketProxy class) to easily simulate network outages.
A full writeup and source code are available at
https://github.com/jkorab/activemq-dsls
As it stands, the DSL is a work in progress that supports my own code,
but I think it would be useful as something provided by ActiveMQ itself.
I would like to contribute what I have written so far, and develop it
further (perhaps cleaning up a bunch of ActiveMQ tests to use it in an
"eating your own dogfood" way). I was initially thinking that it could
be part of activemq-broker in the src/test tree, and once it gets
fleshed out, moved to src/main. The set of config options in ActiveMQ is
huge, and retrofitting tests would be an ideal way of evolving it and
validating that everything works before making it public.
I think that this is something that would be useful, as I have seen
ActiveMQ deployments where the broker was defined in Java. This is
particularly useful where there are is a broker network with a bunch of
network connectors from a broker, each with dynamically or statically
included or excluded destinations, used in conjuction with composite
destinations to route messages in "just the right way". That sort of
thing is much better expressed in code rather than huge slabs of XML.
What do you think? Is this something that would be worthwhile to have in
ActiveMQ?
Jakub
Re: ActiveMQ DSLs
Posted by Christian Posta <ch...@gmail.com>.
I like this idea. ActiveMQ is a pretty complicated piece of software with
all of its configuration options. Writing unit/integration tests that try
to capture some edge case, or odd configuration combination, does end up
getting hairy, duplicative, and difficult to understand and maintain. A DSL
like this could help reduce some of that noise. At the very minimum we
should get this/something like this into the testing code base and use that
as a way to refine/improve the DSL API and our unit tests.
On Fri, Mar 13, 2015 at 9:13 AM, Jakub Korab <ja...@gmail.com>
wrote:
> Hi All,
>
> In working on a separate project, I found the need to instantiate multiple
> different ActiveMQ configurations. Rather than writing up a lot of
> different XML configs or messing around with assembling BrokerService
> instances, I wrote a DSL that mimics the ActiveMQ config schema via a
> directed builder pattern, much like Camel. Here's an example:
>
> BrokerContext context = new BrokerContext(ActiveMQBrokers.
> broker("embeddedBroker").useJmx(false).persistent(false)
> .transportConnectors()
> .transportConnector("openwire", "tcp://0.0.0.0:61616").end()
> .end()
> .plugins()
> .simpleAuthenticationPlugin()
> .users()
> .authenticationUser("user").password("pass").groups("guests").end()
> .end()
> .end()
> .end()));
>
> context.start();
> ...
> context.end();
>
> Unlike Camel, the DSL itself defines a model that is used to instantiate a
> BrokerService. Camel has an intermediate set of VOs
> (org.apache.camel.model) between the Java DSL and the implementation. I had
> a go at generating a similar model via JAXB from the ActiveMQ schema, to
> abstract away the DSL/XBean config, but the generated classes were hideous
> and I abandoned the approach.
>
> I also developed a testing DSL for JUnit that allows you to spin up these
> configurations, and rely on the JUnit runner to start up and shut down the
> broker. The test DSL also allows for the definition of proxies (using the
> ActiveMQ SocketProxy class) to easily simulate network outages.
>
> A full writeup and source code are available at
>
> https://github.com/jkorab/activemq-dsls
>
> As it stands, the DSL is a work in progress that supports my own code, but
> I think it would be useful as something provided by ActiveMQ itself. I
> would like to contribute what I have written so far, and develop it further
> (perhaps cleaning up a bunch of ActiveMQ tests to use it in an "eating your
> own dogfood" way). I was initially thinking that it could be part of
> activemq-broker in the src/test tree, and once it gets fleshed out, moved
> to src/main. The set of config options in ActiveMQ is huge, and
> retrofitting tests would be an ideal way of evolving it and validating that
> everything works before making it public.
>
> I think that this is something that would be useful, as I have seen
> ActiveMQ deployments where the broker was defined in Java. This is
> particularly useful where there are is a broker network with a bunch of
> network connectors from a broker, each with dynamically or statically
> included or excluded destinations, used in conjuction with composite
> destinations to route messages in "just the right way". That sort of thing
> is much better expressed in code rather than huge slabs of XML.
>
> What do you think? Is this something that would be worthwhile to have in
> ActiveMQ?
>
> Jakub
>
--
*Christian Posta*
twitter: @christianposta
http://www.christianposta.com/blog
http://fabric8.io
Re: ActiveMQ DSLs
Posted by Jakub Korab <ja...@gmail.com>.
My view of this is that this sort of thing is useful to about 5-10% of
users for an actual deployment.
What I have seen out in the field is that there are instances where
users need to access a single broker, which is their entry point into a
broader topology. The routing of messages at such a broker tends to
become selective
(dynamicallyIncludedDestination/staticallyIncludedDestination etc.). To
prevent network loops, you may start using composite destinations to
rewrite messages into queues whose only reason is to be consumed by a
network connector. As the number of queues increases, so does the amount
of config. I have seen configs that run into hundreds of lines, with a
lot of cut and paste.
Allowing someone to define a broker programatically allows you to cut
down on the repetition, and removes likely misconfigurations. So, I have
seen instances where people do this, through piecing together a
BrokerService by hand. The problem with this approach is that it quickly
becomes unreadable. Syntatic sugar makes it easy to comprehend what
exactly is going on to anyone maintaining (or just re-reading the code a
month later), and mimicking the XML config means it's easy to apply the
documentation.
So the JSON or YAML thing doesn't address this use case - it's just
another form of markup. It doesn't mean that it couldn't be done. The
hurdle is that ActiveMQ doesn't actually have an intermediate config
model - the XBean annotations sit over the implementation classes. If
such a model existed you could apply a set of classes that overlay YAML,
JSON bindings or whatever language DSLs over the top. What would make
this really neat would be that you could pull out the model that
configured a running broker, and redisplay it in XML via JMX a-la Camel.
Jakub
On 13/03/15 20:07, Hadrian Zbarcea wrote:
> Good job, but I don't think it's a good idea. Sure, interesting
> syntactic sugar, but what problem does it solve? Who would use it?
> Json or YAML would be way more interesting imho.
>
> Hadrian
>
> On 03/13/2015 12:13 PM, Jakub Korab wrote:
>> Hi All,
>>
>> In working on a separate project, I found the need to instantiate
>> multiple different ActiveMQ configurations. Rather than writing up a lot
>> of different XML configs or messing around with assembling BrokerService
>> instances, I wrote a DSL that mimics the ActiveMQ config schema via a
>> directed builder pattern, much like Camel. Here's an example:
>>
>> BrokerContext context = new
>> BrokerContext(ActiveMQBrokers.broker("embeddedBroker").useJmx(false).persistent(false)
>>
>>
>> .transportConnectors()
>> .transportConnector("openwire",
>> "tcp://0.0.0.0:61616").end()
>> .end()
>> .plugins()
>> .simpleAuthenticationPlugin()
>> .users()
>> .authenticationUser("user").password("pass").groups("guests").end()
>> .end()
>> .end()
>> .end()));
>>
>> context.start();
>> ...
>> context.end();
>>
>> Unlike Camel, the DSL itself defines a model that is used to instantiate
>> a BrokerService. Camel has an intermediate set of VOs
>> (org.apache.camel.model) between the Java DSL and the implementation. I
>> had a go at generating a similar model via JAXB from the ActiveMQ
>> schema, to abstract away the DSL/XBean config, but the generated classes
>> were hideous and I abandoned the approach.
>>
>> I also developed a testing DSL for JUnit that allows you to spin up
>> these configurations, and rely on the JUnit runner to start up and shut
>> down the broker. The test DSL also allows for the definition of proxies
>> (using the ActiveMQ SocketProxy class) to easily simulate network
>> outages.
>>
>> A full writeup and source code are available at
>>
>> https://github.com/jkorab/activemq-dsls
>>
>> As it stands, the DSL is a work in progress that supports my own code,
>> but I think it would be useful as something provided by ActiveMQ itself.
>> I would like to contribute what I have written so far, and develop it
>> further (perhaps cleaning up a bunch of ActiveMQ tests to use it in an
>> "eating your own dogfood" way). I was initially thinking that it could
>> be part of activemq-broker in the src/test tree, and once it gets
>> fleshed out, moved to src/main. The set of config options in ActiveMQ is
>> huge, and retrofitting tests would be an ideal way of evolving it and
>> validating that everything works before making it public.
>>
>> I think that this is something that would be useful, as I have seen
>> ActiveMQ deployments where the broker was defined in Java. This is
>> particularly useful where there are is a broker network with a bunch of
>> network connectors from a broker, each with dynamically or statically
>> included or excluded destinations, used in conjuction with composite
>> destinations to route messages in "just the right way". That sort of
>> thing is much better expressed in code rather than huge slabs of XML.
>>
>> What do you think? Is this something that would be worthwhile to have in
>> ActiveMQ?
>>
>> Jakub
>>
Re: ActiveMQ DSLs
Posted by Dejan Bosanac <de...@nighttale.net>.
Yup, Jira + pull request is a good start
Regards
--
Dejan Bosanac
----------------------
Red Hat, Inc.
dbosanac@redhat.com
Twitter: @dejanb
Blog: http://sensatic.net
ActiveMQ in Action: http://www.manning.com/snyder/
On Tue, Mar 17, 2015 at 11:59 AM, Jakub Korab <ja...@gmail.com>
wrote:
> Just taking a look through the source tree, given that all the tests are
> in activemq-unit-tests, it doesn't make a structural difference. Keeping it
> external might make sense as it would be an optional extra.
>
> I also have a test DSL as a sub-project of my source tree that uses JUnit
> 4.11 (same version as used by ActiveMQ) @Rule annotations, which get the
> test runner to manage the lifecycle of the DSL-defined broker (as opposed
> to writing the same setUp() and tearDown() methods all the time). It allows
> lookups of transport connector URIs for easy ConnectionFactory
> instantiation, and also does transparent network proxying via a SocketProxy.
>
> |public class MyEmbeddedBrokerTest {
> @Rule
> public ProxiedBrokerResource broker = new BrokerResource(
> ActiveMQBrokers.broker("embeddedBroker").useJmx(false)
> .persistent(false)
> .transportConnectors()
> .transportConnector("openwire", "tcp://0.0.0.0:61616
> ").end()
> .transportConnector("stomp", "stomp://0.0.0.0:61618
> ").end()
> .end())
> .withProxied("openwire").port(10000); // port to be proxied
> is looked up by name
> // you can define multiple proxies for the one broker!
>
> @Test
> public void testNetworkOutages() {
> ConnectionFactory cf =
> new ActiveMQConnectionFactory(
> "failover:(" + broker.getTcpConnectionUri("openwire") +
> ")"); // returns proxied port 10000
> // ...
> SocketProxy socketProxy = broker.getProxy("openwire");
> socketProxy.close(); // network goes down
> // ...
> socketProxy.reopen(); // network comes back up
> }
> }|
>
>
> I would like to drop it in to an activemq-test-dsl project - that would
> allow its use in unit tests, as well as by anyone external who would like
> to make use of it. Does that sound good?
>
> I think that the general consensus is to go ahead. How do I go about doing
> this? Should I log in in Jira, and issue a pull request from a git branch?
>
> Jakub
>
>
> On 17/03/15 10:30, Dejan Bosanac wrote:
>
>> That’s fine by me as well. It’s just that I don’t see it as much of a
>> burden on activemq-broker. It really is just a couple of classes in it’s
>> own package which can be used to configure and run the broker from Java.
>> If
>> it’s a separate module, than we need to make sure we include it
>> activemq-all, activemq-osgi, etc, and add it as a dependency to all
>> modules
>> that want to use it for testing. So in the end it will be more
>> complicated.
>> But whatever folks prefer is fine by me.
>>
>> Regards
>> --
>> Dejan Bosanac
>> ----------------------
>> Red Hat, Inc.
>> dbosanac@redhat.com
>> Twitter: @dejanb
>> Blog: http://sensatic.net
>> ActiveMQ in Action: http://www.manning.com/snyder/
>>
>> On Tue, Mar 17, 2015 at 11:17 AM, Hadrian Zbarcea <hz...@gmail.com>
>> wrote:
>>
>> How about a separate jar that could be used in conjunction with
>>> activemq-broker? In time start moving 'nice to have' things from
>>> activemq-broker into this other jar?
>>>
>>> Hadrian
>>>
>>>
>>> On 03/17/2015 05:57 AM, Dejan Bosanac wrote:
>>>
>>> IMHO it should be enough to just put these classes in the new package
>>>> (something like org.apache.activemq.broker.dsl) inside the
>>>> activemq-broker
>>>> module.
>>>>
>>>> Regards
>>>> --
>>>> Dejan Bosanac
>>>> ----------------------
>>>> Red Hat, Inc.
>>>> dbosanac@redhat.com
>>>> Twitter: @dejanb
>>>> Blog: http://sensatic.net
>>>> ActiveMQ in Action: http://www.manning.com/snyder/
>>>>
>>>> On Tue, Mar 17, 2015 at 12:26 AM, artnaseef <ar...@artnaseef.com> wrote:
>>>>
>>>> That's an interesting use-case, and I see the value there.
>>>>
>>>>> Would this be a new, separate artifact or a change to an existing one?
>>>>>
>>>>> Art
>>>>>
>>>>> P.S. apologies for confusion on my earlier post - using nabble's "raw"
>>>>> content did indeed cause the content of the post to get stripped in
>>>>> email
>>>>> somehow.
>>>>>
>>>>>
>>>>>
>>>>> --
>>>>> View this message in context:
>>>>> http://activemq.2283324.n4.nabble.com/ActiveMQ-DSLs-
>>>>> tp4693171p4693332.html
>>>>> Sent from the ActiveMQ - Dev mailing list archive at Nabble.com.
>>>>>
>>>>>
>>>>>
>
Re: ActiveMQ DSLs
Posted by Jakub Korab <ja...@gmail.com>.
Just taking a look through the source tree, given that all the tests are
in activemq-unit-tests, it doesn't make a structural difference. Keeping
it external might make sense as it would be an optional extra.
I also have a test DSL as a sub-project of my source tree that uses
JUnit 4.11 (same version as used by ActiveMQ) @Rule annotations, which
get the test runner to manage the lifecycle of the DSL-defined broker
(as opposed to writing the same setUp() and tearDown() methods all the
time). It allows lookups of transport connector URIs for easy
ConnectionFactory instantiation, and also does transparent network
proxying via a SocketProxy.
|public class MyEmbeddedBrokerTest {
@Rule
public ProxiedBrokerResource broker = new BrokerResource(
ActiveMQBrokers.broker("embeddedBroker").useJmx(false).persistent(false)
.transportConnectors()
.transportConnector("openwire", "tcp://0.0.0.0:61616").end()
.transportConnector("stomp", "stomp://0.0.0.0:61618").end()
.end())
.withProxied("openwire").port(10000); // port to be proxied is looked up by name
// you can define multiple proxies for the one broker!
@Test
public void testNetworkOutages() {
ConnectionFactory cf =
new ActiveMQConnectionFactory(
"failover:(" + broker.getTcpConnectionUri("openwire") + ")"); // returns proxied port 10000
// ...
SocketProxy socketProxy = broker.getProxy("openwire");
socketProxy.close(); // network goes down
// ...
socketProxy.reopen(); // network comes back up
}
}|
I would like to drop it in to an activemq-test-dsl project - that would
allow its use in unit tests, as well as by anyone external who would
like to make use of it. Does that sound good?
I think that the general consensus is to go ahead. How do I go about
doing this? Should I log in in Jira, and issue a pull request from a git
branch?
Jakub
On 17/03/15 10:30, Dejan Bosanac wrote:
> That’s fine by me as well. It’s just that I don’t see it as much of a
> burden on activemq-broker. It really is just a couple of classes in it’s
> own package which can be used to configure and run the broker from Java. If
> it’s a separate module, than we need to make sure we include it
> activemq-all, activemq-osgi, etc, and add it as a dependency to all modules
> that want to use it for testing. So in the end it will be more complicated.
> But whatever folks prefer is fine by me.
>
> Regards
> --
> Dejan Bosanac
> ----------------------
> Red Hat, Inc.
> dbosanac@redhat.com
> Twitter: @dejanb
> Blog: http://sensatic.net
> ActiveMQ in Action: http://www.manning.com/snyder/
>
> On Tue, Mar 17, 2015 at 11:17 AM, Hadrian Zbarcea <hz...@gmail.com>
> wrote:
>
>> How about a separate jar that could be used in conjunction with
>> activemq-broker? In time start moving 'nice to have' things from
>> activemq-broker into this other jar?
>>
>> Hadrian
>>
>>
>> On 03/17/2015 05:57 AM, Dejan Bosanac wrote:
>>
>>> IMHO it should be enough to just put these classes in the new package
>>> (something like org.apache.activemq.broker.dsl) inside the
>>> activemq-broker
>>> module.
>>>
>>> Regards
>>> --
>>> Dejan Bosanac
>>> ----------------------
>>> Red Hat, Inc.
>>> dbosanac@redhat.com
>>> Twitter: @dejanb
>>> Blog: http://sensatic.net
>>> ActiveMQ in Action: http://www.manning.com/snyder/
>>>
>>> On Tue, Mar 17, 2015 at 12:26 AM, artnaseef <ar...@artnaseef.com> wrote:
>>>
>>> That's an interesting use-case, and I see the value there.
>>>> Would this be a new, separate artifact or a change to an existing one?
>>>>
>>>> Art
>>>>
>>>> P.S. apologies for confusion on my earlier post - using nabble's "raw"
>>>> content did indeed cause the content of the post to get stripped in email
>>>> somehow.
>>>>
>>>>
>>>>
>>>> --
>>>> View this message in context:
>>>> http://activemq.2283324.n4.nabble.com/ActiveMQ-DSLs-
>>>> tp4693171p4693332.html
>>>> Sent from the ActiveMQ - Dev mailing list archive at Nabble.com.
>>>>
>>>>
Re: ActiveMQ DSLs
Posted by Dejan Bosanac <de...@nighttale.net>.
That’s fine by me as well. It’s just that I don’t see it as much of a
burden on activemq-broker. It really is just a couple of classes in it’s
own package which can be used to configure and run the broker from Java. If
it’s a separate module, than we need to make sure we include it
activemq-all, activemq-osgi, etc, and add it as a dependency to all modules
that want to use it for testing. So in the end it will be more complicated.
But whatever folks prefer is fine by me.
Regards
--
Dejan Bosanac
----------------------
Red Hat, Inc.
dbosanac@redhat.com
Twitter: @dejanb
Blog: http://sensatic.net
ActiveMQ in Action: http://www.manning.com/snyder/
On Tue, Mar 17, 2015 at 11:17 AM, Hadrian Zbarcea <hz...@gmail.com>
wrote:
> How about a separate jar that could be used in conjunction with
> activemq-broker? In time start moving 'nice to have' things from
> activemq-broker into this other jar?
>
> Hadrian
>
>
> On 03/17/2015 05:57 AM, Dejan Bosanac wrote:
>
>> IMHO it should be enough to just put these classes in the new package
>> (something like org.apache.activemq.broker.dsl) inside the
>> activemq-broker
>> module.
>>
>> Regards
>> --
>> Dejan Bosanac
>> ----------------------
>> Red Hat, Inc.
>> dbosanac@redhat.com
>> Twitter: @dejanb
>> Blog: http://sensatic.net
>> ActiveMQ in Action: http://www.manning.com/snyder/
>>
>> On Tue, Mar 17, 2015 at 12:26 AM, artnaseef <ar...@artnaseef.com> wrote:
>>
>> That's an interesting use-case, and I see the value there.
>>>
>>> Would this be a new, separate artifact or a change to an existing one?
>>>
>>> Art
>>>
>>> P.S. apologies for confusion on my earlier post - using nabble's "raw"
>>> content did indeed cause the content of the post to get stripped in email
>>> somehow.
>>>
>>>
>>>
>>> --
>>> View this message in context:
>>> http://activemq.2283324.n4.nabble.com/ActiveMQ-DSLs-
>>> tp4693171p4693332.html
>>> Sent from the ActiveMQ - Dev mailing list archive at Nabble.com.
>>>
>>>
>>
Re: ActiveMQ DSLs
Posted by Hadrian Zbarcea <hz...@gmail.com>.
How about a separate jar that could be used in conjunction with
activemq-broker? In time start moving 'nice to have' things from
activemq-broker into this other jar?
Hadrian
On 03/17/2015 05:57 AM, Dejan Bosanac wrote:
> IMHO it should be enough to just put these classes in the new package
> (something like org.apache.activemq.broker.dsl) inside the activemq-broker
> module.
>
> Regards
> --
> Dejan Bosanac
> ----------------------
> Red Hat, Inc.
> dbosanac@redhat.com
> Twitter: @dejanb
> Blog: http://sensatic.net
> ActiveMQ in Action: http://www.manning.com/snyder/
>
> On Tue, Mar 17, 2015 at 12:26 AM, artnaseef <ar...@artnaseef.com> wrote:
>
>> That's an interesting use-case, and I see the value there.
>>
>> Would this be a new, separate artifact or a change to an existing one?
>>
>> Art
>>
>> P.S. apologies for confusion on my earlier post - using nabble's "raw"
>> content did indeed cause the content of the post to get stripped in email
>> somehow.
>>
>>
>>
>> --
>> View this message in context:
>> http://activemq.2283324.n4.nabble.com/ActiveMQ-DSLs-tp4693171p4693332.html
>> Sent from the ActiveMQ - Dev mailing list archive at Nabble.com.
>>
>
Re: ActiveMQ DSLs
Posted by Dejan Bosanac <de...@nighttale.net>.
IMHO it should be enough to just put these classes in the new package
(something like org.apache.activemq.broker.dsl) inside the activemq-broker
module.
Regards
--
Dejan Bosanac
----------------------
Red Hat, Inc.
dbosanac@redhat.com
Twitter: @dejanb
Blog: http://sensatic.net
ActiveMQ in Action: http://www.manning.com/snyder/
On Tue, Mar 17, 2015 at 12:26 AM, artnaseef <ar...@artnaseef.com> wrote:
> That's an interesting use-case, and I see the value there.
>
> Would this be a new, separate artifact or a change to an existing one?
>
> Art
>
> P.S. apologies for confusion on my earlier post - using nabble's "raw"
> content did indeed cause the content of the post to get stripped in email
> somehow.
>
>
>
> --
> View this message in context:
> http://activemq.2283324.n4.nabble.com/ActiveMQ-DSLs-tp4693171p4693332.html
> Sent from the ActiveMQ - Dev mailing list archive at Nabble.com.
>
Re: ActiveMQ DSLs
Posted by artnaseef <ar...@artnaseef.com>.
That's an interesting use-case, and I see the value there.
Would this be a new, separate artifact or a change to an existing one?
Art
P.S. apologies for confusion on my earlier post - using nabble's "raw"
content did indeed cause the content of the post to get stripped in email
somehow.
--
View this message in context: http://activemq.2283324.n4.nabble.com/ActiveMQ-DSLs-tp4693171p4693332.html
Sent from the ActiveMQ - Dev mailing list archive at Nabble.com.
Re: ActiveMQ DSLs
Posted by Hadrian Zbarcea <hz...@gmail.com>.
I will add another couple of thoughts on this topic. I totally get that,
and I agree.
My thinking though is that outside testing, where yes, it could be very
convenient, I doubt it will find much use in production. The main reason
is that one would very likely have to change code in order to
reconfigure the broker. In practice, there are way more stringent rules
for code deployment than configuration changes. Sometimes that's what
one wants, treating configuration as code and limit changes, but then
one could very well deliver the activemq.xml configuration in a
jar/bundle with the same effect.
So anyway, from a production perspective, very limited benefit, I see it
mostly as bloat. From a community perspective, I have very bad
experience with larger jars, with a large number of packages and
classes, sometimes just alternatives for each other. They tend to be
confusing and off-putting for new contributors. From a vendor
perspective, I do see the appeal of providing more 'features'. I try to
resist the temptation.
I hope that clarifies the rationale behind my previous statements.
Cheers,
Hadrian
On 03/16/2015 08:39 AM, Dejan Bosanac wrote:
> I like this approach of configuring the brokers. I see it as as very
> powerful tool for writing complex unit tests, which can make our lives
> easier. On the other hand, I don’t see any reason why wouldn’t we include
> it in the code base. It doesn’t affect the core, so it’s not a
> stability/performance risk, nor it is a big maintenance burden.
>
> Regards
> --
> Dejan Bosanac
> ----------------------
> Red Hat, Inc.
> dbosanac@redhat.com
> Twitter: @dejanb
> Blog: http://sensatic.net
> ActiveMQ in Action: http://www.manning.com/snyder/
>
> On Sat, Mar 14, 2015 at 1:44 PM, Jakub Korab <ja...@gmail.com>
> wrote:
>
>> The end() idiom was just something I put in to make it clear when an
>> element was closing (there's no way to easily express the difference
>> between an attribute and a subelement of a config node, or when an element
>> is finishing). I'm not married to any particular syntax here, and it
>> definitely has room for improvement.
>>
>> Just to refer back to my previous reply to Hadrian, imagine this sort of
>> thing, and you get a much better idea as to where my thinking is heading
>> with regard to the power of a DSL.
>>
>> String[] destinationsToReplicate = new String[] {"a", "b", "c", "d",
>> "e"...};
>>
>> List<VirtualDestinationDefinition> virtualDestinations = new
>> ArrayList()<>;
>> for (String destination : destinationsToReplicate} {
>> virtualDestinations.add(
>> compositeQueue(destination) // statically included method
>> .forwardOnly(true)
>> .forwardTo()
>> .queue("toNY." + destination)
>> .queue("toLN." + destination)
>> .topic("audit." + destination));
>> }
>>
>> ActiveMQBrokers.broker("TY.orderRouter")
>> .destinationInterceptors()
>> .virtualDestinationInterception()
>> .withVirtualDestinations(virtualDestinations)
>> .networkConnectors()
>> .networkConnector("TY-NY", "tcp...")
>> .staticallyIncludedDestinations("toNY.>")
>> .networkConnector("TY-LN", "tcp...")
>> .staticallyIncludedDestinations("toLN.>");
>>
>> Tiny amount of code, lots of work being performed, easy to comprehend and
>> maintain.
>>
>> If you had multiple brokers in different geographical locations, you could
>> inject all the string values from some config into a template broker
>> definition, and have a standard deployed process that uses this DSL spin up
>> a uniformly configured broker specific to that location. That's something
>> you can't do with ease right now.
>>
>> Jakub
>>
>>
>> On 13/03/15 22:18, David Jencks wrote:
>>
>>> Unfortunately your sample didn't show up on the mailing list…. I had to
>>> resort to looking at nabble.
>>>
>>> I think your example is too simple to see the benefits of a fluent api.
>>> For instance, you haven't added an object that itself needs configuration
>>> to a collection (e.g. transport connector). My experience is that they
>>> make configuring anything reasonably complicated 10x simpler and more
>>> pleasant :-)
>>>
>>> That being said….. I'm not familiar with the ".end()" idiom. Is this
>>> common? "standard"? I'd think it would be less confusing if they were
>>> .endTransportConnectors() etc so it was clear what you were ending.
>>>
>>> thanks
>>> david jencks
>>>
>>>
>>> On Mar 13, 2015, at 5:32 PM, artnaseef <ar...@artnaseef.com> wrote:
>>>
>>> I see "fluent is easier" as a valid argument to maintaining the project,
>>>> but
>>>> not necessarily as a reason to pull it into the ActiveMQ main code base.
>>>>
>>>> Still, I am 50/50 on this myself. I personally don't have a need for
>>>> simpler configuration of embedded brokers. Also, the syntax of fluent
>>>> builders doesn't appeal to me personally, so that makes it harder for me
>>>> to
>>>> buy-in. For example:
>>>>
>>>> Seems simpler to understand than (I'm making this one up - not using the
>>>> posted language):
>>>>
>>>> With that said - I acknowledge this is my opinion and welcome some
>>>> discussion of the benefit of including the code inside of ActiveMQ itself
>>>> (beyond the well-understood "it will then be maintained with the core
>>>> code").
>>>>
>>>> Art
>>>>
>>>>
>>>>
>>>> --
>>>> View this message in context: http://activemq.2283324.n4.
>>>> nabble.com/ActiveMQ-DSLs-tp4693171p4693202.html
>>>> Sent from the ActiveMQ - Dev mailing list archive at Nabble.com.
>>>>
>>>
>>
>
Re: ActiveMQ DSLs
Posted by Dejan Bosanac <de...@nighttale.net>.
I like this approach of configuring the brokers. I see it as as very
powerful tool for writing complex unit tests, which can make our lives
easier. On the other hand, I don’t see any reason why wouldn’t we include
it in the code base. It doesn’t affect the core, so it’s not a
stability/performance risk, nor it is a big maintenance burden.
Regards
--
Dejan Bosanac
----------------------
Red Hat, Inc.
dbosanac@redhat.com
Twitter: @dejanb
Blog: http://sensatic.net
ActiveMQ in Action: http://www.manning.com/snyder/
On Sat, Mar 14, 2015 at 1:44 PM, Jakub Korab <ja...@gmail.com>
wrote:
> The end() idiom was just something I put in to make it clear when an
> element was closing (there's no way to easily express the difference
> between an attribute and a subelement of a config node, or when an element
> is finishing). I'm not married to any particular syntax here, and it
> definitely has room for improvement.
>
> Just to refer back to my previous reply to Hadrian, imagine this sort of
> thing, and you get a much better idea as to where my thinking is heading
> with regard to the power of a DSL.
>
> String[] destinationsToReplicate = new String[] {"a", "b", "c", "d",
> "e"...};
>
> List<VirtualDestinationDefinition> virtualDestinations = new
> ArrayList()<>;
> for (String destination : destinationsToReplicate} {
> virtualDestinations.add(
> compositeQueue(destination) // statically included method
> .forwardOnly(true)
> .forwardTo()
> .queue("toNY." + destination)
> .queue("toLN." + destination)
> .topic("audit." + destination));
> }
>
> ActiveMQBrokers.broker("TY.orderRouter")
> .destinationInterceptors()
> .virtualDestinationInterception()
> .withVirtualDestinations(virtualDestinations)
> .networkConnectors()
> .networkConnector("TY-NY", "tcp...")
> .staticallyIncludedDestinations("toNY.>")
> .networkConnector("TY-LN", "tcp...")
> .staticallyIncludedDestinations("toLN.>");
>
> Tiny amount of code, lots of work being performed, easy to comprehend and
> maintain.
>
> If you had multiple brokers in different geographical locations, you could
> inject all the string values from some config into a template broker
> definition, and have a standard deployed process that uses this DSL spin up
> a uniformly configured broker specific to that location. That's something
> you can't do with ease right now.
>
> Jakub
>
>
> On 13/03/15 22:18, David Jencks wrote:
>
>> Unfortunately your sample didn't show up on the mailing list…. I had to
>> resort to looking at nabble.
>>
>> I think your example is too simple to see the benefits of a fluent api.
>> For instance, you haven't added an object that itself needs configuration
>> to a collection (e.g. transport connector). My experience is that they
>> make configuring anything reasonably complicated 10x simpler and more
>> pleasant :-)
>>
>> That being said….. I'm not familiar with the ".end()" idiom. Is this
>> common? "standard"? I'd think it would be less confusing if they were
>> .endTransportConnectors() etc so it was clear what you were ending.
>>
>> thanks
>> david jencks
>>
>>
>> On Mar 13, 2015, at 5:32 PM, artnaseef <ar...@artnaseef.com> wrote:
>>
>> I see "fluent is easier" as a valid argument to maintaining the project,
>>> but
>>> not necessarily as a reason to pull it into the ActiveMQ main code base.
>>>
>>> Still, I am 50/50 on this myself. I personally don't have a need for
>>> simpler configuration of embedded brokers. Also, the syntax of fluent
>>> builders doesn't appeal to me personally, so that makes it harder for me
>>> to
>>> buy-in. For example:
>>>
>>> Seems simpler to understand than (I'm making this one up - not using the
>>> posted language):
>>>
>>> With that said - I acknowledge this is my opinion and welcome some
>>> discussion of the benefit of including the code inside of ActiveMQ itself
>>> (beyond the well-understood "it will then be maintained with the core
>>> code").
>>>
>>> Art
>>>
>>>
>>>
>>> --
>>> View this message in context: http://activemq.2283324.n4.
>>> nabble.com/ActiveMQ-DSLs-tp4693171p4693202.html
>>> Sent from the ActiveMQ - Dev mailing list archive at Nabble.com.
>>>
>>
>
Re: ActiveMQ DSLs
Posted by Jakub Korab <ja...@gmail.com>.
The end() idiom was just something I put in to make it clear when an
element was closing (there's no way to easily express the difference
between an attribute and a subelement of a config node, or when an
element is finishing). I'm not married to any particular syntax here,
and it definitely has room for improvement.
Just to refer back to my previous reply to Hadrian, imagine this sort of
thing, and you get a much better idea as to where my thinking is heading
with regard to the power of a DSL.
String[] destinationsToReplicate = new String[] {"a", "b", "c", "d",
"e"...};
List<VirtualDestinationDefinition> virtualDestinations = new ArrayList()<>;
for (String destination : destinationsToReplicate} {
virtualDestinations.add(
compositeQueue(destination) // statically included method
.forwardOnly(true)
.forwardTo()
.queue("toNY." + destination)
.queue("toLN." + destination)
.topic("audit." + destination));
}
ActiveMQBrokers.broker("TY.orderRouter")
.destinationInterceptors()
.virtualDestinationInterception()
.withVirtualDestinations(virtualDestinations)
.networkConnectors()
.networkConnector("TY-NY", "tcp...")
.staticallyIncludedDestinations("toNY.>")
.networkConnector("TY-LN", "tcp...")
.staticallyIncludedDestinations("toLN.>");
Tiny amount of code, lots of work being performed, easy to comprehend
and maintain.
If you had multiple brokers in different geographical locations, you
could inject all the string values from some config into a template
broker definition, and have a standard deployed process that uses this
DSL spin up a uniformly configured broker specific to that location.
That's something you can't do with ease right now.
Jakub
On 13/03/15 22:18, David Jencks wrote:
> Unfortunately your sample didn't show up on the mailing list…. I had to resort to looking at nabble.
>
> I think your example is too simple to see the benefits of a fluent api. For instance, you haven't added an object that itself needs configuration to a collection (e.g. transport connector). My experience is that they make configuring anything reasonably complicated 10x simpler and more pleasant :-)
>
> That being said….. I'm not familiar with the ".end()" idiom. Is this common? "standard"? I'd think it would be less confusing if they were .endTransportConnectors() etc so it was clear what you were ending.
>
> thanks
> david jencks
>
>
> On Mar 13, 2015, at 5:32 PM, artnaseef <ar...@artnaseef.com> wrote:
>
>> I see "fluent is easier" as a valid argument to maintaining the project, but
>> not necessarily as a reason to pull it into the ActiveMQ main code base.
>>
>> Still, I am 50/50 on this myself. I personally don't have a need for
>> simpler configuration of embedded brokers. Also, the syntax of fluent
>> builders doesn't appeal to me personally, so that makes it harder for me to
>> buy-in. For example:
>>
>> Seems simpler to understand than (I'm making this one up - not using the
>> posted language):
>>
>> With that said - I acknowledge this is my opinion and welcome some
>> discussion of the benefit of including the code inside of ActiveMQ itself
>> (beyond the well-understood "it will then be maintained with the core
>> code").
>>
>> Art
>>
>>
>>
>> --
>> View this message in context: http://activemq.2283324.n4.nabble.com/ActiveMQ-DSLs-tp4693171p4693202.html
>> Sent from the ActiveMQ - Dev mailing list archive at Nabble.com.
Re: ActiveMQ DSLs
Posted by David Jencks <da...@yahoo.com.INVALID>.
Unfortunately your sample didn't show up on the mailing list…. I had to resort to looking at nabble.
I think your example is too simple to see the benefits of a fluent api. For instance, you haven't added an object that itself needs configuration to a collection (e.g. transport connector). My experience is that they make configuring anything reasonably complicated 10x simpler and more pleasant :-)
That being said….. I'm not familiar with the ".end()" idiom. Is this common? "standard"? I'd think it would be less confusing if they were .endTransportConnectors() etc so it was clear what you were ending.
thanks
david jencks
On Mar 13, 2015, at 5:32 PM, artnaseef <ar...@artnaseef.com> wrote:
> I see "fluent is easier" as a valid argument to maintaining the project, but
> not necessarily as a reason to pull it into the ActiveMQ main code base.
>
> Still, I am 50/50 on this myself. I personally don't have a need for
> simpler configuration of embedded brokers. Also, the syntax of fluent
> builders doesn't appeal to me personally, so that makes it harder for me to
> buy-in. For example:
>
> Seems simpler to understand than (I'm making this one up - not using the
> posted language):
>
> With that said - I acknowledge this is my opinion and welcome some
> discussion of the benefit of including the code inside of ActiveMQ itself
> (beyond the well-understood "it will then be maintained with the core
> code").
>
> Art
>
>
>
> --
> View this message in context: http://activemq.2283324.n4.nabble.com/ActiveMQ-DSLs-tp4693171p4693202.html
> Sent from the ActiveMQ - Dev mailing list archive at Nabble.com.
Re: ActiveMQ DSLs
Posted by artnaseef <ar...@artnaseef.com>.
I see "fluent is easier" as a valid argument to maintaining the project, but
not necessarily as a reason to pull it into the ActiveMQ main code base.
Still, I am 50/50 on this myself. I personally don't have a need for
simpler configuration of embedded brokers. Also, the syntax of fluent
builders doesn't appeal to me personally, so that makes it harder for me to
buy-in. For example:
Seems simpler to understand than (I'm making this one up - not using the
posted language):
With that said - I acknowledge this is my opinion and welcome some
discussion of the benefit of including the code inside of ActiveMQ itself
(beyond the well-understood "it will then be maintained with the core
code").
Art
--
View this message in context: http://activemq.2283324.n4.nabble.com/ActiveMQ-DSLs-tp4693171p4693202.html
Sent from the ActiveMQ - Dev mailing list archive at Nabble.com.
Re: ActiveMQ DSLs
Posted by David Jencks <da...@yahoo.com.INVALID>.
Speaking as a non-user of AMQ, I would say that if this fluent approach is easier to use than the existing way of configuring and starting a broker in java, then it should be added to AMQ.
thanks
david jencks
On Mar 13, 2015, at 4:13 PM, artnaseef <ar...@artnaseef.com> wrote:
> I'm 50/50 on this. Like Hadrian said, it's nice syntax, but does it really
> add value? I don't see anything there that cannot be done already via java
> code - is that right?
>
> I think this is a good project to maintain, but not sure it should go into
> ActiveMQ itself.
>
>
>
> --
> View this message in context: http://activemq.2283324.n4.nabble.com/ActiveMQ-DSLs-tp4693171p4693187.html
> Sent from the ActiveMQ - Dev mailing list archive at Nabble.com.
Re: ActiveMQ DSLs
Posted by artnaseef <ar...@artnaseef.com>.
I'm 50/50 on this. Like Hadrian said, it's nice syntax, but does it really
add value? I don't see anything there that cannot be done already via java
code - is that right?
I think this is a good project to maintain, but not sure it should go into
ActiveMQ itself.
--
View this message in context: http://activemq.2283324.n4.nabble.com/ActiveMQ-DSLs-tp4693171p4693187.html
Sent from the ActiveMQ - Dev mailing list archive at Nabble.com.
Re: ActiveMQ DSLs
Posted by Hadrian Zbarcea <hz...@gmail.com>.
Good job, but I don't think it's a good idea. Sure, interesting
syntactic sugar, but what problem does it solve? Who would use it? Json
or YAML would be way more interesting imho.
Hadrian
On 03/13/2015 12:13 PM, Jakub Korab wrote:
> Hi All,
>
> In working on a separate project, I found the need to instantiate
> multiple different ActiveMQ configurations. Rather than writing up a lot
> of different XML configs or messing around with assembling BrokerService
> instances, I wrote a DSL that mimics the ActiveMQ config schema via a
> directed builder pattern, much like Camel. Here's an example:
>
> BrokerContext context = new
> BrokerContext(ActiveMQBrokers.broker("embeddedBroker").useJmx(false).persistent(false)
>
> .transportConnectors()
> .transportConnector("openwire", "tcp://0.0.0.0:61616").end()
> .end()
> .plugins()
> .simpleAuthenticationPlugin()
> .users()
> .authenticationUser("user").password("pass").groups("guests").end()
> .end()
> .end()
> .end()));
>
> context.start();
> ...
> context.end();
>
> Unlike Camel, the DSL itself defines a model that is used to instantiate
> a BrokerService. Camel has an intermediate set of VOs
> (org.apache.camel.model) between the Java DSL and the implementation. I
> had a go at generating a similar model via JAXB from the ActiveMQ
> schema, to abstract away the DSL/XBean config, but the generated classes
> were hideous and I abandoned the approach.
>
> I also developed a testing DSL for JUnit that allows you to spin up
> these configurations, and rely on the JUnit runner to start up and shut
> down the broker. The test DSL also allows for the definition of proxies
> (using the ActiveMQ SocketProxy class) to easily simulate network outages.
>
> A full writeup and source code are available at
>
> https://github.com/jkorab/activemq-dsls
>
> As it stands, the DSL is a work in progress that supports my own code,
> but I think it would be useful as something provided by ActiveMQ itself.
> I would like to contribute what I have written so far, and develop it
> further (perhaps cleaning up a bunch of ActiveMQ tests to use it in an
> "eating your own dogfood" way). I was initially thinking that it could
> be part of activemq-broker in the src/test tree, and once it gets
> fleshed out, moved to src/main. The set of config options in ActiveMQ is
> huge, and retrofitting tests would be an ideal way of evolving it and
> validating that everything works before making it public.
>
> I think that this is something that would be useful, as I have seen
> ActiveMQ deployments where the broker was defined in Java. This is
> particularly useful where there are is a broker network with a bunch of
> network connectors from a broker, each with dynamically or statically
> included or excluded destinations, used in conjuction with composite
> destinations to route messages in "just the right way". That sort of
> thing is much better expressed in code rather than huge slabs of XML.
>
> What do you think? Is this something that would be worthwhile to have in
> ActiveMQ?
>
> Jakub
>
Re: ActiveMQ DSLs
Posted by Jean-Baptiste Onofré <jb...@nanthrax.net>.
I second Tim there. Good job !
Regards
JB
On 03/13/2015 07:08 PM, Timothy Bish wrote:
> On 03/13/2015 12:13 PM, Jakub Korab wrote:
>> Hi All,
>>
>> In working on a separate project, I found the need to instantiate
>> multiple different ActiveMQ configurations. Rather than writing up a
>> lot of different XML configs or messing around with assembling
>> BrokerService instances, I wrote a DSL that mimics the ActiveMQ config
>> schema via a directed builder pattern, much like Camel. Here's an
>> example:
>>
>> BrokerContext context = new
>> BrokerContext(ActiveMQBrokers.broker("embeddedBroker").useJmx(false).persistent(false)
>>
>> .transportConnectors()
>> .transportConnector("openwire", "tcp://0.0.0.0:61616").end()
>> .end()
>> .plugins()
>> .simpleAuthenticationPlugin()
>> .users()
>> .authenticationUser("user").password("pass").groups("guests").end()
>> .end()
>> .end()
>> .end()));
>>
>> context.start();
>> ...
>> context.end();
>>
>> Unlike Camel, the DSL itself defines a model that is used to
>> instantiate a BrokerService. Camel has an intermediate set of VOs
>> (org.apache.camel.model) between the Java DSL and the implementation.
>> I had a go at generating a similar model via JAXB from the ActiveMQ
>> schema, to abstract away the DSL/XBean config, but the generated
>> classes were hideous and I abandoned the approach.
>>
>> I also developed a testing DSL for JUnit that allows you to spin up
>> these configurations, and rely on the JUnit runner to start up and
>> shut down the broker. The test DSL also allows for the definition of
>> proxies (using the ActiveMQ SocketProxy class) to easily simulate
>> network outages.
>>
>> A full writeup and source code are available at
>>
>> https://github.com/jkorab/activemq-dsls
>>
>> As it stands, the DSL is a work in progress that supports my own code,
>> but I think it would be useful as something provided by ActiveMQ
>> itself. I would like to contribute what I have written so far, and
>> develop it further (perhaps cleaning up a bunch of ActiveMQ tests to
>> use it in an "eating your own dogfood" way). I was initially thinking
>> that it could be part of activemq-broker in the src/test tree, and
>> once it gets fleshed out, moved to src/main. The set of config options
>> in ActiveMQ is huge, and retrofitting tests would be an ideal way of
>> evolving it and validating that everything works before making it public.
>>
>> I think that this is something that would be useful, as I have seen
>> ActiveMQ deployments where the broker was defined in Java. This is
>> particularly useful where there are is a broker network with a bunch
>> of network connectors from a broker, each with dynamically or
>> statically included or excluded destinations, used in conjuction with
>> composite destinations to route messages in "just the right way". That
>> sort of thing is much better expressed in code rather than huge slabs
>> of XML.
>>
>> What do you think? Is this something that would be worthwhile to have
>> in ActiveMQ?
>>
>> Jakub
>>
> Cool stuff, definitely seems like something we ought to consider adding.
>
--
Jean-Baptiste Onofré
jbonofre@apache.org
http://blog.nanthrax.net
Talend - http://www.talend.com
Re: ActiveMQ DSLs
Posted by Timothy Bish <ta...@gmail.com>.
On 03/13/2015 12:13 PM, Jakub Korab wrote:
> Hi All,
>
> In working on a separate project, I found the need to instantiate
> multiple different ActiveMQ configurations. Rather than writing up a
> lot of different XML configs or messing around with assembling
> BrokerService instances, I wrote a DSL that mimics the ActiveMQ config
> schema via a directed builder pattern, much like Camel. Here's an
> example:
>
> BrokerContext context = new
> BrokerContext(ActiveMQBrokers.broker("embeddedBroker").useJmx(false).persistent(false)
> .transportConnectors()
> .transportConnector("openwire", "tcp://0.0.0.0:61616").end()
> .end()
> .plugins()
> .simpleAuthenticationPlugin()
> .users()
> .authenticationUser("user").password("pass").groups("guests").end()
> .end()
> .end()
> .end()));
>
> context.start();
> ...
> context.end();
>
> Unlike Camel, the DSL itself defines a model that is used to
> instantiate a BrokerService. Camel has an intermediate set of VOs
> (org.apache.camel.model) between the Java DSL and the implementation.
> I had a go at generating a similar model via JAXB from the ActiveMQ
> schema, to abstract away the DSL/XBean config, but the generated
> classes were hideous and I abandoned the approach.
>
> I also developed a testing DSL for JUnit that allows you to spin up
> these configurations, and rely on the JUnit runner to start up and
> shut down the broker. The test DSL also allows for the definition of
> proxies (using the ActiveMQ SocketProxy class) to easily simulate
> network outages.
>
> A full writeup and source code are available at
>
> https://github.com/jkorab/activemq-dsls
>
> As it stands, the DSL is a work in progress that supports my own code,
> but I think it would be useful as something provided by ActiveMQ
> itself. I would like to contribute what I have written so far, and
> develop it further (perhaps cleaning up a bunch of ActiveMQ tests to
> use it in an "eating your own dogfood" way). I was initially thinking
> that it could be part of activemq-broker in the src/test tree, and
> once it gets fleshed out, moved to src/main. The set of config options
> in ActiveMQ is huge, and retrofitting tests would be an ideal way of
> evolving it and validating that everything works before making it public.
>
> I think that this is something that would be useful, as I have seen
> ActiveMQ deployments where the broker was defined in Java. This is
> particularly useful where there are is a broker network with a bunch
> of network connectors from a broker, each with dynamically or
> statically included or excluded destinations, used in conjuction with
> composite destinations to route messages in "just the right way". That
> sort of thing is much better expressed in code rather than huge slabs
> of XML.
>
> What do you think? Is this something that would be worthwhile to have
> in ActiveMQ?
>
> Jakub
>
Cool stuff, definitely seems like something we ought to consider adding.
--
Tim Bish
Sr Software Engineer | RedHat Inc.
tim.bish@redhat.com | www.redhat.com
skype: tabish121 | twitter: @tabish121
blog: http://timbish.blogspot.com/