tag:blogger.com,1999:blog-67014476020115047162023-06-20T05:42:19.724-07:00Mitko's blogUnknownnoreply@blogger.comBlogger3125tag:blogger.com,1999:blog-6701447602011504716.post-63217311910110295242011-11-25T13:08:00.001-08:002011-12-14T03:52:59.928-08:00On the Daily Scrum<span style="font-size: large;">Introduction</span><br />
In a team environment, collaboration is essential for achieving the goals within a time-boxed iteration. Within the Scrum process, it is a subject to the Daily Scrum implementation to <i>establish</i> collaboration context within the team, and <i>expose the benefits </i>of the collaboration, so an appropriate implementation is necessary. Additionally, enforcing collaboration in Scrum is essential in the absence of a command-and-control manager to enforce it, to justify the absence of the manager.<br />
This blog post introduces a new tool named <i>collaboration board</i> and a proposed Daily Scrum implementation with corresponding question to fill the <i>collaboration board</i>.<br />
<span style="font-size: large;">The Daily Scrum </span><br />
One of the few building blocks of the Scrum framework is the Daily Scrum a.k.a. Stand-up, at which each team member answers the three questions: <br />
<ul>
<li>What have I done since yesterday?</li>
<li>What am I planning to do today?</li>
<li>Any impediments?</li>
</ul>
The participants need to understand what could the answers of these questions change. Who should use the answers, and what for? This explanation can be essential for establishing an attitude towards the process, and on the long term even influence the performance and work satisfaction of the participants.<br />
<span style="font-size: small;"><b><i></i></b></span> <br />
<span style="font-size: large;">The command-and-control project management style</span><br />
Scrum is a set of simple rules of a<i> framework </i>that is an <i>alternative </i>to command-and-control management style. It is important to understand, that the role of the command-and-control manager is to be <i>compensated </i>by an empowered team. In order to justify the team empowerment and the absence of the command-and-control manager, the team members <i>has to</i> make some effort. That is it: with the Scrum framework, if the team members are <b><i>informative</i></b>, <b><i>cooperative</i></b>, <i><b>disciplined </b></i><b>and </b><i><b>contribute</b></i>, the team as an entity <i>does not need</i> a command-and-control manager. The Daily Scrum is supposed to target the informative and cooperative part on a daily basis, to serve as an <b><i>information exchange</i></b> activity and <b><i>provide context for collaboration</i></b>. <br />
It is important to understand the Daily Scrum as an activity used to provide <i>information exchange</i> and <i>context for collaboration.</i><b><i> </i></b>However, at least in the company I work for, people tend to consider the daily Scrum as a scene, on which the participants <i><span style="font-size: large;"><b>report</b> </span></i>to a product owner.<br />
<span style="font-size: large;">What is the problem with <i>reporting</i>?</span><br />
Let's see what follows if we take part in the Daily Standup with that <i>reporting</i> attitude (to report e.g. to the product owner). If the daily Stand-up is understood as reporting, people tend to put themselves in a defensive position, because <i>to report</i> is associated with being <i>subordinate</i> and <i>managed</i>. To <i>inform</i> does not necessarily impose a mood of being <i>subordinate </i>and <i>managed</i>. As result, with that feeling it is difficult to enjoy and maybe impossible to benefit from the Scrum process as well as contribute to improvements.<br />
What needs to be done here is to use a different understanding of inform, to absorb that defensive facet that comes by the reporting association. In this sense, it would be appropriate to put the focus <i>on the patterns</i> used to implement the task, and on the <i>benefits of collaboration </i>within the team, that contributed for the task achievement. The benefits can be for example, <i>concept validation / feedback</i>, <i>experience sharing</i>, <i>cut-down development time </i>or <i>leveraging creativity</i>.<br />
<br />
<span style="font-size: large;">Proposed </span><span style="font-size: large;">Daily Scrum </span><span style="font-size: large;">Implementation</span><br />
So what do we do to assert that this attitude be changed in order to:<br />
<ul>
<li>expose the <i>benefits of the team collaboration</i> and have the participants <i>develop positive attitude</i> with the time towards the process (perhaps increase satisfaction); </li>
<li>justify the absence of command-and-control manager<i> for the information exchange and collaboration </i>responsibilities;<i><br />
</i></li>
<li>implementation the Daily Scrum in a way that does <i>not </i>suppress people;</li>
</ul>
Here is my proposal to address the bullet points above in the Daily Scrum.<br />
<br />
<span style="font-size: large;">"What have I done since yesterday?"</span><br />
<b>Time-boxed within 2 minutes.</b> <b>Take some time to prepare yourself</b>, otherwise you will not fit into the 2 minutes.<br />
<ul>
<li>Give a short answer of the question in 2-3 short sentences using <b><i>the header descriptions of the issues only</i></b>.</li>
<li>With whom<i> did you collaborate</i>? <i>If someone gave you ideas and help, give this person a +1 on the <b>collaboration board</b></i>.<b> </b>Use at least the following dimensions for the reasons you gave a +1:<b> ideas, workforce, feedback</b> (add new or remove if appropriate). Here are some example outcomes from collaboration: <i>results from</i> <i>code review</i>, <i>a success story</i>, a <i>big improvement</i>, <i>new pattern, the simplest solution etc. </i></li>
<li>Was it something big that you would like to share? Invite the team to a session where you have enough time to say what you want.</li>
<li><b>Set a person to give you feedback</b> from what you did, if you worked on the task/tasks alone.</li>
</ul>
<div style="font-family: inherit;">
<span style="font-size: large;">"What am I planning to do today?"</span></div>
<b>Time-boxed within 1 minute. </b>Say briefly what you will do, using <b>the header descriptions of the issues.</b><br />
<ul>
<li>How do you estimate the task in terms of complexity?</li>
<li><b>After the stand-up</b> discuss the approach and/or outline the solution with a domain expert, if there is any. Find yourself a collaboration partner within the team.</li>
</ul>
<div style="font-family: inherit;">
<span style="font-size: large;">"Any impediments?"</span></div>
<div style="font-family: inherit;">
<span style="font-size: large;"><span style="font-size: small;">Extract the information that concerns the team. Prepare to be short and clear. Explain the details to your ScrumMaster in a 1:1. </span></span></div>Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-6701447602011504716.post-47434191693679099932011-06-16T07:18:00.000-07:002011-09-23T01:11:02.396-07:00HL7 2.x DSL with auto-completion<span style="font-size: large;">Introduction </span><br />
<br />
Have you ever worked with a <a href="http://en.wikipedia.org/wiki/Health_Level_7">HL7</a> 2.x [1]? Have you ever tried to extract information from a HL7 2.x message or even validate such a message against an <a href="http://www.ihe.net/">IHE</a> [2] profile with the <a href="http://hl7api.sourceforge.net/">HAPI library</a> [3]? The purpose of the blog post is to announce that there is a Groovy [4] domain specific language (<a href="http://www.martinfowler.com/bliki/DomainSpecificLanguage.html">DSL</a>) [5] that helps you work simpler with HL7 2.x messages. Most important, a Groovy DSL with auto-completion. To understand everything in this blog post, you need some basic knowledge about HL7 2.x and the HAPI library. <br />
<br />
<span style="font-size: large;">Why bother to create a HL7 2.x DSL with auto-completion?</span><br />
<br />
HL7 is basically defined by a proprietary schema. The HAPI project has a legal permission to use this schema. What HAPI does is to generate Java classes, based on an abstract model for every version of HL7 2.x.<br />
The need to <b>extend HAPI</b> has motivated the creation of
such Groovy DSL, and why Groovy? Because in Groovy it is easy to create DSLs.
However, there is something that has been somehow underestimated when it comes to DSLs - the IDE support. <b>The IDE should be able help with both usage and verification of such DSL, and take away that burden from developers</b>. Unfortunately not all IDEs support descriptors for Groovy, that are powerful enough to model such HL7 2.x DSL extensions. The good news: thanks to the <a href="http://groovy.codehaus.org/Eclipse+Plugin">Groovy Eclipse plugin version 2.5+</a> [6], the Eclipse IDE has <a href="http://blog.springsource.com/2011/05/08/better-dsl-support-in-groovy-eclipse/%20">this power</a> [7].
<br />
<br />
<span style="font-size: large;">How to get the HL7 2.x DSL?</span><br />
<br />
The proposed <b>HL7 2.x DSL is part of the <a href="http://repo.openehealth.org/confluence/display/ipf2/IPF+reference+-+multi">Open eHealth IPF project</a></b> [9]. If you use Maven 2,<b> add the the HL7 DSL dependency</b> in your <span style="font-family: 'Courier New',Courier,monospace;">pom.xml</span>. Replace <span style="font-family: 'Courier New',Courier,monospace;">${ipf-version} </span>with <span style="font-family: 'Courier New',Courier,monospace;">2.3-m2</span> or higher.
<br />
<pre class="java" name="code"><dependency>
<groupid>org.openehealth.ipf.modules</groupid>
<artifactid>modules-hl7dsl</artifactid>
<version>${ipf-version}</version>
</dependency>
</pre>
You will find the dependency in the <a href="http://repo.openehealth.org/maven2/releases/">Open eHealth Maven repository</a> [8].<br />
Next you have to <b>add the dependencies with the generated HAPI structures you need</b>. For example, if you work only with structures version 2.6, leave only the <span style="font-family: 'Courier New',Courier,monospace;">hapi-structures-v26</span> dependency.
<br />
<pre class="java" name="code"><dependency>
<groupid>ca.uhn.hapi</groupid>
<artifactid>hapi-structures-v25</artifactid>
<version>1.0.1</version>
</dependency>
<dependency>
<groupid>ca.uhn.hapi</groupid>
<artifactid>hapi-structures-v251</artifactid>
<version>1.0.1</version>
</dependency>
<dependency>
<groupid>ca.uhn.hapi</groupid>
<artifactid>hapi-structures-v26</artifactid>
<version>1.0.1</version>
</dependency>
</pre>
<br />
<br />
<span style="font-size: large;">What are the benefits of the HL7 2.x DSL? </span><br />
<br />
Before I show how to use the DSL, I would like to list briefly its benefits:<br />
<br />
<ul>
<li> Groups and Segments can be <b>accessed by name</b> like an object property. This brings readability and HL7-like syntax. For example <span style="font-family: 'Courier New',Courier,monospace;">message.MSH</span> will access the <span style="font-family: 'Courier New',Courier,monospace;">MSH </span>segment in a message. </li>
<li> Fields <b>are accessed like an array field</b>; <b>components in a composite field are accessed like a multi-dimension array</b>. For example: <span style="font-family: 'Courier New',Courier,monospace;">message.MSH[9][1]</span> will return the message type</li>
<li>The internal structure changes between HL7 versions. In higher versions,
primitive fields are sometimes replaced with composite fields, having
the so far used primitive as first component. Using the DSL you can <b>access the fileds by name</b>. If the field or group is non-repeatable, the first element is returned. For example, <span style="font-family: 'Courier New',Courier,monospace;">message.PATIENT_RESULT(0).PATIENT</span> will equal <span style="font-family: 'Courier New',Courier,monospace;">message.PATIENT_RESULT.PATIENT
</span></li>
<li><b>Support for <span style="font-family: 'Courier New',Courier,monospace;">isEmpty()</span> method for all adapted HAPI elements </b>(<span style="font-family: 'Courier New',Courier,monospace;">ca.uhn.hl7v2.model.Segment</span>, <span style="font-family: 'Courier New',Courier,monospace;">ca.uhn.hl7v2.model.Group </span>and all kind of <span style="font-family: 'Courier New',Courier,monospace;">ca.uhn.hl7v2.model.Type</span>, inclusive <span style="font-family: 'Courier New',Courier,monospace;">ca.uhn.hl7v2.model.Composite</span> types).</li>
<li><b>Support for getPath() method</b>; Here is a quick example. For a ORU_R01 message: <span style="font-family: 'Courier New',Courier,monospace;">msg.PATIENT_RESULT(1).PATIENT.PID.path</span> will return <span style="font-family: 'Courier New',Courier,monospace;"> "PATIENT_RESULT(1).PATIENT.PID"</span> (1 means the second repetition of PATIENT_RESULT, <b>works only with the access by name</b>)</li>
<li><b>Adding repettions</b>, for example <span style="font-family: 'Courier New',Courier,monospace;">new MessageAdapter(</span><span class="code-keyword" style="font-family: 'Courier New',Courier,monospace;">new</span><span style="font-family: 'Courier New',Courier,monospace;"> ORU_R01()).PATIENT_RESULT(0) </span>will add a <span style="font-family: 'Courier New',Courier,monospace;">PATIENT_RESULT</span> group to the empty message.</li>
<li><b>Manipulating segments and fields</b>, for example <span style="font-family: 'Courier New',Courier,monospace;">msg1.EVN.from(msg2.EVN) </span>copies the EVN segment from <span style="font-family: 'Courier New',Courier,monospace;">msg2</span> to <span style="font-family: 'Courier New',Courier,monospace;">msg1</span></li>
</ul>
<span style="font-size: large;">How does the auto-completion work?</span><br />
<br />
Well, first you have to type in a Eclipse Groovy editor. The Groovy Eclipse plug-in's type-inferencing engine, with the help of a DSLD descriptor provided by the DSL library, does most of it. The DSLD descriptor publishes callbacks that are invoked when the Groovy abstract syntax tree is being modified. However, the implementation needs a hint - your <b>adapter declaration must be parametrized with generics</b>. That's it, the rest is done by the DSLD descriptor of the DSL library and the plug-in's inferencing engine.
Imagine that you adapt a version 2.4 ORU_R01 message. Your adapter definition should be parametrized with generics like this:<br />
<br />
<pre class="java" name="code">import static org.openehealth.ipf.modules.hl7dsl.MessageAdapters.load
import org.openehealth.ipf.modules.hl7dsl.MessageAdapter
import ca.uhn.hl7v2.model.v24.message.ORU_R01
...
MessageAdapter <ORU_R01> msg = load('msg-oru-r01.hl7');
...
</pre>
Notice the generic argument <span style="font-family: 'Courier New',Courier,monospace;">ORU_R01</span>.<b> If you do not use the generic arg, you will not profit from the auto-completion</b>.<br />
<br />
<span style="font-size: large;">Examples</span><br />
<br />
Let's say you have declared the <span style="font-family: 'Courier New',Courier,monospace;">msg2</span> object as in the previous section:<br />
<span style="font-family: 'Courier New',Courier,monospace;"> MessageAdapter <ORU_R01> msg2 = load('msg-oru-r01.hl7'); </span><b>When you hit ctrl + space after <span style="font-family: 'Courier New',Courier,monospace;">msg2.</span> you will get the suggestions</b>. The following two screen-shots show the access by name in action.<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="http://3.bp.blogspot.com/-N2TSL4ZIIIU/TfoD46SswMI/AAAAAAAALos/_ptlftvTi3Y/s1600/patientResult.bmp" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" height="166" src="http://3.bp.blogspot.com/-N2TSL4ZIIIU/TfoD46SswMI/AAAAAAAALos/_ptlftvTi3Y/s640/patientResult.bmp" width="640" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Auto-completion after access by name of the second repetition of PATIENT_RESULT group</td></tr>
</tbody></table>
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="http://2.bp.blogspot.com/-WIvisTSVAvk/TfoD9nF25eI/AAAAAAAALow/JhJcqfy9U10/s1600/patientResultPath.bmp" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" height="160" src="http://2.bp.blogspot.com/-WIvisTSVAvk/TfoD9nF25eI/AAAAAAAALow/JhJcqfy9U10/s640/patientResultPath.bmp" width="640" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">DSL Documenation. Notice the currentType (SegmentAdapter in bold)</td></tr>
</tbody></table>
<b><span style="font-size: small;">You </span>also have suggestions for the adapter HAPI objects.</b><b> It is valid to call the regular HAPI methods on those objects</b>. You can use the suggested methods, however in this case the <span style="font-family: 'Courier New',Courier,monospace;">getPath()</span> method will return an empty <span style="font-family: 'Courier New',Courier,monospace;">String</span> object. As said before <span style="font-family: 'Courier New',Courier,monospace;">getPath()</span> currently works only with access by name.<span style="font-family: 'Courier New',Courier,monospace;"></span><br />
<table cellpadding="0" cellspacing="0" class="tr-caption-container" style="float: left; margin-right: 1em; text-align: left;"><tbody>
<tr><td style="text-align: center;"><a href="http://3.bp.blogspot.com/-DDt4MpAjNR8/TfoHOm8vdzI/AAAAAAAALo0/aDQRkZ4CQ2Y/s1600/patientResultHAPI.bmp" imageanchor="1" style="clear: left; margin-bottom: 1em; margin-left: auto; margin-right: auto;"><img border="0" height="184" src="http://3.bp.blogspot.com/-DDt4MpAjNR8/TfoHOm8vdzI/AAAAAAAALo0/aDQRkZ4CQ2Y/s640/patientResultHAPI.bmp" width="640" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Notice the HAPI documentation on the left. Notice the getAt(Integer) method - provided by the DSL as well.</td></tr>
</tbody></table>
<br />
<br />
<span style="font-size: large;">What is currently not working?</span><br />
<ul>
<li><span style="font-size: large;"><span style="font-size: small;">If you use the DSL for <span style="font-family: 'Courier New',Courier,monospace;">getAt(Integer)</span>(a.k.a. the [] syntax) on a <span style="font-family: 'Courier New',Courier,monospace;">SegmentAdapter</span> you get the wrong proposals for <span style="font-family: 'Courier New',Courier,monospace;">SegmentAdapter</span> after the <span style="font-family: 'Courier New',Courier,monospace;">getAt(Integer)</span>. So <b>do not use the auto-completion after the [] DSL. The returned type is TypeAdapter in this case</b>. Example: if you hit <b>ctrl + space after </b><span style="font-family: 'Courier New',Courier,monospace;"><b>msg.MSH[1].</b></span> you will get the proposals for the <span style="font-family: 'Courier New',Courier,monospace;">SegmentAdapter</span>. This will be fixed in the next versions of the Groovy Eclipse Plugin - there is already a task for it.</span></span></li>
<li><b><span style="font-size: large;"><span style="font-size: small;"><span style="font-family: inherit;">Sometimes the auto-completion does not return the </span></span></span><span style="font-size: large;"><span style="font-size: small;"><span style="font-family: 'Courier New',Courier,monospace;"><span style="font-family: inherit;"><span style="font-family: 'Courier New',Courier,monospace;">SegmentAdapter </span></span></span></span></span></b><span style="font-size: large;"><span style="font-size: small;"><span style="font-family: inherit;"><b>type. It returns <span style="font-family: 'Courier New',Courier,monospace;">Object </span>instead</b>. I hope that this will be fixed soon.</span></span></span></li>
</ul>
<br />
<span style="font-size: large;">Conclusion
</span><br />
The Open eHealth IPF project has a HL7 2.x DSL module. The module comes with a DSLD descriptor that provides type inference information in Eclipse. The DSL in a combination with the auto-completion helps to navigate and access the HL7 elements easily. Many thanks to the Open eHealth IPF project team and the people who developed the Groovy Eclipse plugin.<br />
<br />
<span style="font-size: large;">References</span><br />
[1] HL7 <a href="http://en.wikipedia.org/wiki/Health_Level_7">http://en.wikipedia.org/wiki/Health_Level_7</a><br />
[2] IHE <a href="http://www.ihe.net/">http://www.ihe.net/</a><br />
[3] HAPI library <a href="http://hl7api.sourceforge.net/">http://hl7api.sourceforge.net/</a><br />
[4] Groovy programming language <a href="http://groovy.codehaus.org/" style="font-family: inherit;">http://groovy.codehaus.org/</a> <br />
[5] Domain Specific Language (DSL) <a href="http://www.martinfowler.com/bliki/DomainSpecificLanguage.html">http://www.martinfowler.com/bliki/DomainSpecificLanguage.html</a><br />
[6] Groovy Eclipse plugin <a href="http://groovy.codehaus.org/Eclipse+Plugin">http://groovy.codehaus.org/Eclipse+Plugin</a><br />
[7] Better DSL support in Groovy-Eclipse <a href="http://blog.springsource.com/2011/05/08/better-dsl-support-in-groovy-eclipse/%20">http://blog.springsource.com/2011/05/08/better-dsl-support-in-groovy-eclipse/ </a><br />
[8] Open eHealth Maven repository <a href="http://repo.openehealth.org/maven2/releases/">http://repo.openehealth.org/maven2/releases/</a><br />
[9] Open eHealth IPF project Wiki<a href="http://repo.openehealth.org/confluence/display/ipf2/IPF+reference+-+multi"> http://repo.openehealth.org/confluence/display/ipf2/IPF+reference+-+multi</a>Unknownnoreply@blogger.com069190 Walldorf, Germany49.30315 8.6427569999999649.277216 8.6060159999999613 49.329084 8.67949799999996tag:blogger.com,1999:blog-6701447602011504716.post-21298855994383729652011-02-28T13:00:00.000-08:002011-06-16T22:48:29.796-07:00Is it possible to extend the Java DSL of Apache Camel in Java?<br />
<span style="font-size: large;">Introduction </span><br />
<br />
This post contains my experiments to <i>extend</i> the <a href="http://camel.apache.org/">Apache Camel</a> Java DSL, also referred to as route builder fluent API. I'll try to clarify what I mean by <span style="font-family: inherit;"><i>extend</i></span> with an example. With Camel (version 2.6) you are able to create a route like this: <br />
<pre class="java" name="code">...
from("direct:start").to("direct:end")
...
</pre>
By <i>extend</i> the fluent API, I mean <i>being able to add a new elements to the existing set of API elements</i>, e.g. <span style="font-family: "Courier New",Courier,monospace;">beep()</span>. Some route that uses those new route elements might look like this: <br />
<pre class="java" name="code">...
from("direct:start").beep().to("direct:end")
...
</pre>
In the route above, the <span style="font-family: "Courier New",Courier,monospace;">beep()</span>element is not part of the Camel DSL. To stay focused, I will neither discuss the extensions with Groovy, Scala or other JVM languages other than Java, nor the motivation for having DLS extensions in Java.<span style="font-size: large;"> </span><br />
<br />
<span style="font-size: large;">Extend the DSL, but how?</span> <br />
<br />
My experiment was driven by the idea to <i>extend the DSL using an N-tuple of custom (<span style="font-family: "Courier New",Courier,monospace;">MyRouteBuilder</span>, <span style="font-family: "Courier New",Courier,monospace;">MyRouteDefinition</span>, <span style="font-family: "Courier New",Courier,monospace;">My1stProcessorDefinition</span>, ... , <span style="font-family: "Courier New",Courier,monospace;">MyNthProcessorDefinition</span>)</i>, that are subclases of <span style="font-family: "Courier New",Courier,monospace;">RouteBuilder</span>, <span style="font-family: "Courier New",Courier,monospace;">RouteDefintiion</span> and <span style="font-family: "Courier New",Courier,monospace;">ProcessorDefinition</span>. <br />
To use the extended DSL I would subclass <span style="font-family: "Courier New",Courier,monospace;">MyRouteBuilder</span> and write the route just as I would write it when I subclass Camel's <span style="font-family: "Courier New",Courier,monospace;">RouteBuilder</span>. As you would expect <span style="font-family: "Courier New",Courier,monospace;">MyRouteBuilder</span> creates <span style="font-family: "Courier New",Courier,monospace;">MyRouteDefinition</span>, that will create <span style="font-family: "Courier New",Courier,monospace;">My1stProcessorDefinition</span> ... <span style="font-family: "Courier New",Courier,monospace;">MyNthProcessorDefinition</span> where applicable. <br />
In this definition the <span style="font-family: "Courier New",Courier,monospace;">beep()</span> extension suggested above would be part of the second element of the tuple, which is <i><span style="font-family: "Courier New",Courier,monospace;">MyRouteDefinition</span></i>. Once again, back to the N-tuple definition; it is neither scientific nor official definition. I introduce it solely, because I believe it clearly explains what I mean. I hope it is correct, please comment if you think I am wrong. <br />
<br />
<span style="font-size: large;">What is the problem? </span><br />
I will try to explain what is currently problematic with the extensions. Here is how a route with a <span style="font-family: "Courier New",Courier,monospace;">beep() </span>extension might look like, using the proposed extension technique. First I define the <span style="font-family: "Courier New",Courier,monospace;">MyRouteBuilder</span>: <br />
<pre class="java" name="code">public abstract class MyRouteBuilder extends RouteBuilder {
public MyRouteBuilder() {
setRouteCollection(new MyRoutesCollection());
}
private class MyRoutesCollection extends RoutesDefinition {
public MyRouteDefinition from (String uri){
// Without the MyRouteDefinition return type
// beep will not be recognized
return (MyRouteDefinition)super.from(uri);
}
//Needed by the overriden from method
protected MyRouteDefinition createRoute() {
MyRouteDefinition result = new MyRouteDefinition();
...
}
}
}
</pre>
Next I can define <span style="font-family: "Courier New",Courier,monospace;">MyRouteDefinition</span> that adds the<span style="font-family: "Courier New",Courier,monospace;"> beep()</span> method: <br />
<pre class="java" name="code">import org.apache.camel.RouteDefinition;
public class MyRouteDefinition extends RouteDefinition {
/**
* My extension method
*/
public MyRouteDefinition beep(){
//beep implementation here
...
return this;
}
}
</pre>
Now the use of the <span style="font-family: "Courier New",Courier,monospace;">beep()</span> extension in the route: <br />
<pre class="java" name="code">public class MyRouteBuilderTest extends MyRouteBuilder{
@Override
public void configure() throws Exception {
// This compiles and runs
from("direct:start")
.beep().to("mock:end");
from("direct:start")
.filter(header("soundAllowed").isEqualTo("true"))
// This does not compile
.beep().to("mock:end");
}
} </pre>
The first problem is the type cast in the <span style="font-family: "Courier New",Courier,monospace;">from(String uri)</span> method in <span style="font-family: "Courier New",Courier,monospace;">MyRouteBuilder</span>. It might seem negligible at first, but I have actually overriden only one of the DSL methods in <span style="font-family: "Courier New",Courier,monospace;">RouteBuilder</span>. Overiding all methods would lead to duplication and inconsistency on new Camel releases.<br />
<br />
The second more obvious problem, is that <span style="font-family: "Courier New",Courier,monospace;">MyRouteBuilderTest </span>does not compile. It does not compile, because the <span style="font-family: "Courier New",Courier,monospace;">filter(...)</span> element returns <span style="font-family: "Courier New",Courier,monospace;">FilterDefinition</span>, and <span style="font-family: "Courier New",Courier,monospace;">FilterDefinition </span>does not have any information about the existence of the<span style="font-family: "Courier New",Courier,monospace;"> beep()</span> extension, since it is not a subclass of <span style="font-family: "Courier New",Courier,monospace;">MyRouteDefinition</span>.<br />
<pre class="java" name="code">import org.apache.camel.RouteDefinition;
public class FilterDefinition extends ExpressionNode {
/**
* My extension method
*/
public MyRouteDefinition beep(){
//beep implementation here
...
return this;
}
}
</pre>
<br />
This means, that I can use my new DSL extensions only direct after <span style="font-family: "Courier New",Courier,monospace;">from()</span>.<br />
<br />
<span style="font-size: large;">Conclusion</span><br />
<br />
The proposed extension mechanism strategy is not applicable in Java, because the new DSL elements are "lost" when standard Camel DSL elements, like <span style="font-family: "Courier New",Courier,monospace;">filter(...)</span> are used. The latter limitation is a source of confusion that might put the acceptance of such a DSL extension approach in question. I am convinced that with some changes in <span style="font-family: "Courier New",Courier,monospace;">camel-core,</span> extensions of this nature are possible in Java. <br />
<br />Unknownnoreply@blogger.com1