The Author Online Book Forums are Moving

The Author Online Book Forums will soon redirect to Manning's liveBook and liveVideo. All book forum content will migrate to liveBook's discussion forum and all video forum content will migrate to liveVideo. Log in to liveBook or liveVideo with your Manning credentials to join the discussion!

Thank you for your engagement in the AoF over the years! We look forward to offering you a more enhanced forum experience.

davsclaus (413) [Avatar] Offline
#1
Hi

We are in production phase with the book, which means we are starting to lock down the chapters, when we complete the copy/tech editing and reviews for each and every chapter.

If you have any comments or suggestions then now its a good time to step forward and post the comments. Its much easier for us to incorporate your suggestions before the chapters is locked down.
gmazza (30) [Avatar] Offline
#2
Re: Time for your last minute comments
Chapter 3 comments:

Section 3.1:
from: Camel have a build in type converter mechanism which automatic can convert between types which greatly reduces the need for type transformation.
to: Camel has a built-in type converter mechanism which automatically can convert between types, greatly reducing the need for type transformation.

3.1.1:
This happens seamless and only component writers need to worry about it.
to *seamlessly*

p. 60: code example is puzzling; the text claims that it provides all orders on a given date but seems to be limited to just one customer (no for loop around customer ID's). Either a code change or a text change describing the code correctly would be a good idea.

p. 62: builded->built (global search and replace); we will cover in more details->detail

p. 63: probably best to include the source code of the HTMLBean class (it's only a few lines) in the book rather than have people hunt down the source code to understand the required signature of its toHtml() method.
davsclaus (413) [Avatar] Offline
#3
Re: Time for your last minute comments
Thanks for reporting. The copy editor have spotted those as well.

I have included the code for the HTMLBean to help demystify what's happening.
gmazza (30) [Avatar] Offline
#4
Re: Time for your last minute comments
Chapter 4 Comments:

Text Changes:
1.) Perhaps a sentence defining what the direct: component does when it is first mentioned in the book would be good. Looking at Listing 4.1, I'm not sure what from("direct:hello") means/does, without going to the Camel site.

2.) Listing 4.2, the bean ID for "route" needs to switch from InvokeWithProcessorRoute to InvokeWithProcessorSpringRoute.

3.) page - 88: In listing 4.3, AFAIK a setter is needed in the code for "private HelloBean hello;" to be Autowired properly; there's no way that Spring automagically can populate that value without a constructor setting that value or a setHello(HelloBean) setter.

4.) page - 89: "Altogether we reduce the code in the inlined Processor from four lines to three." -- that's not why we use Dependency Injection (flexibility is); I'd remove that sentence and instead remind the reader that (AFAIK) a setter is also needed in the code for the Hello bean for @Autowired to work.

5.) page - 89:
mvn test -Dtest=InvokeWithProcessorTest <-- works
mvn test -Dtest=InvokeWithSpringProcessorTest <-- is not working when run from Maven (returns "There are no tests to run." message)

6.) page - 94, Sentence "It [JNDIRegistry] was the first Registry that Camel integrated, so it’s also the default registry if you create a Camel instance without supplying a specific registry as the code below showns" partially contradicts Table 4.1, which says ApplicationContextRegistry is automatically used if you're using Camel in a Spring environment.

7.) page - 94, The Section 4.3.2 code sample isn't showing us how to add HelloBean to the JNDI Registry like 4.3.1 does with SimpleRegistry.

8.) page - 94, sentence fragment: "it's the default when you define Camel in the Spring XML" is too vague, I think you mean "When you define a camelContext in the Spring XML"

9.) page. 102: the end of section 4.4.4, it would be nice to briefly mention how the TextMessage->Document conversion could be handled so that error mentioned would not occur (what type converter or other mechanism to put in the middle to get rid of the error.) Although that info is already covered in Chapter 3, it's good to see a type converter used along with a beanRef.

10.) page 110: "In a real system, we would generate unique order ids based on another scheme." --> "...based on another scheme, perhaps by using the java.util.UUID class."

11.) page 103: "which is to let Camel adapt to the method signature" -> "the process of Camel assigning values to parameters in the method signature"

Editorial matters (copy editor stuff):

12.) page - 96: "where as Java code is linked" -> "whereas the Java code is linked"

13.) page - 97: "ekko does not exists" -> "ekko does not exist"

14.) page 98: "shown in figure 4.5" -> "shown in figure 4.6"

15.) page 100: return echo + " " + eco; --> + echo;
"Camel will pick a method if there is only one method with a single parameter." --> "Camel will pick the method if it is the only one with a single parameter."

16.) page 101: "with the Integer value of 5" italicize entire word "Integer"

17.) page 102: "explicit-->ly<-- specified the method name."

18.) page 102: "could potential be overloaded, which means the bean will have multiple methods with the same name; only the number of parameters will vary." --> "could potential-->ly<-- be overloaded, which means the bean will have multiple methods with the same name -->but with the parameters varying.<--"
gmazza (30) [Avatar] Offline
#5
Re: Time for your last minute comments
Chapter #5

Text Changes:

T1.) p. 114 -- The text is vague on what makes an error irrecoverable, it implies that setting the Body text to an error message will do that, but I think that's really irrelevant, it is the setting of setFault(true) which does that. It also causes one to think that there is a separate object called a "fault message" which really isn't the case. Changing the name of the message variable from "fault" to "msg" and clarifying the importance of setting setFault(true) would make the text more clear, something like the following:

"An irrecoverable error is represented as a fault message that can be set or accessed from org.apache.camel.Exchange." --> "Irrecoverable errors are designated by calling setFault(true) on the Message within the exchange. You will usually also want to change the message body to a fault message."

(change variable name from "fault" to "msg" or similar):
Message msg = Exchange.getOut();
msg.setFault(true);
msg.setBody("Unknown customer");

The text is also a little bit vague in that I'm not sure who can designate an error as irrecoverable -- is it only the Camel developer who does that (and everything is recoverable by default), or does Camel out-of-the-box setFault(true) in some cases?

T2.) p. 115:
"Exceptions is represented as recoverable errors." --> "Recoverable errors are represented as Java Exception instances"
"Fault messages is represented as irrecoverable errors." --> "Irrecoverable errors are designated by calling setFault(true) on the Exchange's Message object."

T3.) p. 116:
"We learned in the previous section that Camel -->initially<-- regards all exceptions as recoverable and stores them on the exchange using the setException(Exception cause) method." (Implies the user can switch it to irrecoverable even if it is first considered recoverable.)

--or--

"We learned in the previous section that Camel regards all recoverable errors as exceptions and stores them on the exchange using the setException(Exception cause) method." (Ignores errors designated by the user as irrecoverable.)

T4.) p. 116:

Text: "The rule of thumb is that error handlers in Camel only trigger when exchange.getException() != null."

Change to:

"The rule of thumb is that error handlers in Camel only trigger when exchange.getException() != null and exchange.getIn()/getOut().getFault() = false."

(Because the sentence preceding this says: "They will not react if an irrecoverable error has been set as a fault message.")

T5.) p. 119: Should explain what the difference is between this:
Exception e = exchange.getProperty(Exchange.CAUSED_EXCEPTION, Exception.class);

and this given on page 114:
Exception e = exchange.getException();

T6.) p. 119: Probably good to also mention that useOriginalMessage() is useful if you do not want potentially decrypted messages in the dead letter queue for security reasons.

T7.) p. 123: useExponentialBackOff should be added to Table 5.3, with the clarification (from the subsequent text) that it's only needed for XML configuration, doesn't need to be set with Java DSL apparently.

T8.) Section 5.5.1, good to show (or just refer people to the Camel site) how to chain onWhens(). ifIllegalData-->this queue, ifDataTooBig-->that queue, if DataTooSmall-->another queue, else-->default queue, etc.



Editorial (copy editor stuff):

E1) page - 114: "Camel has error handling build" --> "built"
"as a fault message that can -->also<-- be set"

E2.) p. 115:
"we start by looking at the different error handlers -->that<-- Camel provides."

E3.) p. 116: "The latter two has-->have limited functionality"

E4.) Figure 5.3: beanRef(order-->Service<--, validate);

E5.) p. 116/Section 5.2.1: missing quotes after orderService:

.beanRef("orderService, "validate")
.beanRef("orderService, "store");

E6.) p. 116: "but you will learn that the default error handler is used in most cases." switch to "DefaultErrorHandler"

E7.) p. 116: "The default error handler is preconfigured and doesn’t need to be explicitly declared in the route." --> "The DefaultErrorHandler doesn't need explicit declaration in the route."

E8.) p. 117: "The Channel is woven in between" (remove word "in")

E9.) p. 117: "The latter is what happens" --> "The last option is what happens"

E10.) Table 5.1 The sentence "We will revisit it in chapter 9." is redundant and can be deleted.

E11.) p. 118: "This is done a bit differently in Java DSL and Spring XML." recommend deleting this sentence (it's obvious) and the "For example, " following it.

E12.) p. 119: "The remaining two error handlers are seldom used and are much more simpler." remove the word "more".

E13.) p. 119: "The current architecture of Camel mandates that an error handler must be configured" switch "mandates" to "requires" and remove word "must".

E14.) p. 119: "standard log format" -> "standard log formats"

E15.) Table 4.2 needs more proofreading/copy editing (at least from the latest MEAP version).

E16.) Table 5.5 "The exception that was caugt" --> caught

E17.) p. 123: "The error handler detects every exception that occurs and acts on it, deciding what to do, such as redeliver or give up (exhaust)." Change "exhaust" to "be exhausted".
davsclaus (413) [Avatar] Offline
#6
Re: Time for your last minute comments
Thanks for the comments.

I have adjusted chapter 4 as well. In fact I added a callout in chapter 3 about the direct component, because it was first used there.

The copy edit stuff will be caught by the professional copy editor.

And there will be a prof editor as well. I wonder if you would like to help with that as well, to spot the language mistakes? For example when the chapters has been adjusted and is being prof read? However I don't know if Manning allows outsiders to help with this.
gmazza (30) [Avatar] Offline
#7
Re: Time for your last minute comments
Ch. 6 Comments

1. p. 142: "This is the "Hello World" example for Integration Kits that copies files from one folder to another."
It *moves* (not copies) files, correct? If so, the test on p. 144 should also check that the originating folder no longer has the file.

2. p. 143: "Beware, Spring 2.5 only works with JUnit 4.4 or lower. Spring 3.0 is required when using JUnit 4.5 or higher." This warning is not that helpful to us, because I don't think the book has told us yet what version of Spring Camel ships with. Some clarification such as "Beware, Spring 2.5 (which Camel 2.X ships with)..." would be helpful in letting us know what version of JUnit we should choose.

3. p. 145, Listing 6.2 -- Clarify that this file is named firststep.xml so people know it's the one being used in Listing 6.3 (which uses that filename).

4. p. 147, for completeness, the tiny rider-prod.properties file should be reproduced on this page, so people know its format--actually, just move its listing on page 151 to page 147.

5. p. 147, Section 6.1.6: "We will cover two solutions how to externalize dynamic parts using properties files. The first solution is based on the Camel properties component and the second leverages Spring property placeholders."

The ordering of the instruction seems wrong IMHO--I think is is more natural to describe the Spring property placeholders *first* (because it's the most well-known standard), and *then* the non-portable Camel properties component (advertising its benefits over the Spring standard--no endpoint elements, for example.) Going from less efficient (but portable) to more efficient (but non-portable) is usually the more common direction.

6. p. 149, "The rider-camel-text.xml file" -> "rider-camel-test.xml file".

7. (Source Code) the chapter6/firsttest has the rider-prod.properties file in src/test/resources, which somewhat defeats the purpose of what you're trying to teach (how the -prod and -test file get combined, and how the former is normally in src/main/resources) I think the prod file should move to src/main/resources, with only the rider-test.properties file remaining in src/test/resources. Everything else should build and test fine with no other changes.

8. p. 150, CamelRiderJavaDSLPest -> CamelRiderJavaDSLTest

9. p. 154, Listing 6.6. I think some discussion should be given here about the line "template.sendBody("jms:topic:quote", "Camel rocks");"--namely, is it completely synchronous so that I can safely rely on the accuracy of the subsequent line of code "quote.assertIsSatisfied();" or is it asynchronous and I need to build in some thread-wait mechanism before I can safely rely on the subsequent assert() statement? The "Note" immediately under it says that assertIsSatisfied() waits 10 seconds by default, so that kind of answers my question that template.sendBody is asynchonous but I think a more explicit statement should be given, something like "Note that you need to take into account the amount of time needed for the route to complete before running the assert statement. assertIsSatisfied() waits 10 seconds by default, etc., etc."

10. p. 155, the statement "Listing 6.6 uses JMS, but for now let’s keep things simple by simulating JMS using the SEDA component." is not clear -- what is the default JMS implementation that CamelTestSupport uses if we use the JMS component and don't override it? Is it Spring's JMS support, or ActiveMQ, or? What is SEDA replacing here?

Also, this entire section "REPLACING JMS WITH SEDA" could arguably be removed because if you're testing JMS you will probably want to use the same underlying provider as you will be using in production, even if SEDA is faster. (Testing SQL statements with Apache Derby, even if faster, isn't showing much if the production DB is Oracle.) But if you retain this section, you may wish to give an advisement over the importance of testing (somewhere, even if at integration level) with the same JMS provider that you'll be using in production.

11. p. 160, Listing 6.8, there is a custom expression that manually reads the exchange headers. That's probably OK, but in certain cases if you're reading the Body and it's an InputStream (as I recently learned) you can only read it once and subsequent test assertions that read that Body will fail because there's nothing left to read. If this is a concern (I'm not sure if it is with the test cases), perhaps a sentence or two should be added, warning the reader of that (i.e., the importance of converting InputStreams to Strings first when doing repeated testing on the same object).

12. p. 164, Listing 6.10, quote: "Notice that we stubbed the file endpoint with a direct endpoint that allows us to start the test by sending a message to it; this is much easier than writing an actual file."

This is not very clear to me--what is the message that we're sending (is it a blank, autogenerated message, or something that we still create?), and in the phrase "by sending a message to it", what is the "it" -- the direct endpoint or the mock:http object?

13. p. 172, "chapter8/notify directory" --> "chapter6/notify directory"
gmazza (30) [Avatar] Offline
#8
Re: Time for your last minute comments
Chapter 7 Comments

1) p. 180, Section 7.2.1: Best to mention the .camel directory is created in the same directory (I guess) that you have processed the files from.

2) p. 184, Section 7.3. To reduce confusion, it might be good to state the difference between ActiveMQ's vm *connector* described in this section, and the vm *component* described on page 213 in Section 7.7. (Are they the same thing?) Probably Section 7.7 would be the better place to clarify this, as both objects are known by then.

3) p. 214, Section 7.7.1: "we can use seda queues for everything else" --> "we can use seda or vm queues for everything else" (vm also according to text on previous page--the three levels are seda, vm, and then JMS).

4) p. 214, Figure 7.14 text: "Figure 7.14 SEDA queues can be used as a low overhead replacement for JMS when messaging is within a -->single<-- CamelContext. For messages being sent to other hosts, JMS can be used. In this case-->example* all order routing is done via SEDA until the order needs to go to the accounting and production departments."

(*use of "case" here is ambiguous--do you mean the example or when JMS is being used, so "example" is better.)

5) p. 215, Section 7.8.1: Sentences: "The timer component comes with Camel's core library and uses the JRE's built in timer mechanism to generate message exchanges at regular intervals. Of course, this component only supports consuming since sending to a timer doesn't really make sense."

I would think this component only supports *producing*, given that it generates messages. The definition of a producer on p. 21 (Section 1.4.2) is this: A Producer is the Camel abstraction that refers to an entity capable of creating and sending a Message to an Endpoint. While a consumer is: A Consumer is the service that receives Messages produced by a client, wraps them in an Exchange, and sends them to be processed.

*New item* added 9/1/2010:
6.) Page 207, Section 7.6.1 on JDBC, Listing 7.4, "Bean that converts an incoming order to an SQL statement" is not done well, it is vulnerable to SQL Injection attacks[1]. If possible, it should be rewritten with parameterized statements (example in [1]) and/or a warning given to the reader cautioning them about the same (a link to [1] and sentence would do fine.) The same occurs in listing 9-1 that I will be providing with my Chapter 9 Notes.

[1] http://en.wikipedia.org/wiki/SQL_injection

Message was edited by: gmazza New item #6 added (SQL injection vulnerability).
gmazza (30) [Avatar] Offline
#9
Re: Time for your last minute comments
Chapter 1 Comment

1.) Section 1.4.2, p. 21, definition of Consumer:

"A Consumer is the service that receives Messages produced by a client, wraps them in an Exchange, and sends them to be processed."

When you say "client", do you mean "Producer"? If yes, it would be much easier for comprehension if you used Producer here, because you haven't defined client, and your usage of the term "client" makes the definition ambiguous--is a client a different object from a Producer or just a synonym for a Producer?

If no, probably good to add a definition for "client" here and mention how it is different from a Producer.
gmazza (30) [Avatar] Offline
#10
Re: Time for your last minute comments
Chapter 8 Notes

1.) p.219 Intro Text: Camel implements nearly all those patterns in addition to 8 -->other<-- patterns."

2.) p.224, Table 8.2, definition of Split Size: "Is the total number of messages being splitted." Unsure, but I think you mean "Total number of submessages that the original message has been split into"

And for SPLIT_INDEX definition, instead of "Is the index for the current message being processed", say is "Is the zero-based [*or* one-based, whichever it is] index for the current submessage being processed"

3.) p.224, Section 8.1.1: Possibly (?) good to let people know how lists of lists would be split by default: List<List><String>>>, for example: submessages of List<String> or tons of submessages of String? (Although the flowchart you gave suggests the former already.)

4.) p.224, S. 8.1.2: In the splitting by department example, you'll probably also want to mention that the same parent Customer-level data will still be duplicated (I think it will, at least) within each new submessage. That could effect people's design decisions in their own work (e.g., changing the packet by stripping out Customer data and just sending Department data) in order to reduce duplicate data.

5.) p.229, S. 8.1.5: The text doesn't tell us what happens with exceptions if we're not aggregating the submessages afterwards (just splitting the original message) *and* we *don't* choose the stopOnException() option. Perhaps a sentence or two should be added on this.

6.) p.231, S. 8.2, "Examples for using Aggregator" shaded block. "Imagine a stock market system..." to "Also imagine a stock market system..." (This example does not follow the example in the preceding sentence so some indication that it is different is needed.)

7.) p.236, S. 8.2.1: Text: "The Aggregator also ensures ordering, which means the messages is aggregated in the same order as they arrive."

The above sentence is misleading because you don't know the order in which the messages will arrive (the above sentence would carry much more weight if it said "the messages are aggregated in the same order that they were originally sent", but I don't think you can make such a blanket statement). So I think some warning or guidance should be given for listing 8.5 (the AggregationStrategy) for the user not to always assume that the messages will be processed in the order in which they were originally sent (e.g., you could get "BCA" or "ACB" instead of always "ABC") and that the aggregation logic may need to take that into account.

8.) p.239, Table 8.6, the definition for eagerCheckCompletion ("Whether or not to eager check for completion.") should define what "eager check" means.

9.) p.242, S 8.2.3, "Running the Example" section, a.txt is listed twice, update the second one to b.txt:

Text: "For example if we copy the first two files and then let the example terminate
cd chapter8/aggregator
chapter8/aggregator$ cp src/test/resources/a.txt target/inbox
chapter8/aggregator$ cp src/test/resources/a.txt-->b.txt target/inbox
"

10.) p.245, S 8.2.3 Text: "The transactional behavior provided by RecoverableAggregationRepository is not based on Spring TransactionManager, which we cover in chapter 9. The transactional behavior is possible due to HawtDB provides its own transaction mechanism."

I think you mean "HawtDBAggregationRepository", *not* "RecoverableAggregationRepository" -- the latter is just an interface and can be implemented in many different ways (possibly including Spring Transaction manager.)

11.) p.248 S. 8.3 Sentence: "The following test method shows how you should fill out the key." recommend switch to clearer "The following test method shows how you can provide this header value."

12.) p.254 S. 8.4.3: For the below failover() example, what if we want to failover if two or more specific exceptions (not just one exception such as IOException in the example) are thrown? How do we chain them--can we?

.loadBalance().failover(IOException.class)
.to("direct:a").to("direct:b")

13.) p.254 S. 8.4.3 Sentence: This allows you to distribute the load evenly between the services and have automatic failover -->to the next service defined in the list<-- as well.

14.) p.257 (Sect. 8.6): The summary doesn't mention the Routing Slip which was also covered.
gmazza (30) [Avatar] Offline
#11
Re: Time for your last minute comments
Chapter 9 Comments

(Also note I edited my Chapter 7 Comments above, adding #6 regarding a SQL injection problem.)

1. Listing 9-1, p. 260:

public String toSql(@XPath("partner/@id") int id, #1
@XPath("partner/date/text()") String date,
@XPath("partner/code/text()") int statusCode,
@XPath("partner/time/text()") long responseTime) {

The Camel XPath page (http://camel.apache.org/xpath.html) does not cover XPath annotations much, so I would refer the reader back to Section 4.5.4 where Camel XPath annotations are covered for those who need a review. (as I did).

Also, on page 261, to clarify this is a Camel construct and not basic Java, insert "Camel" here: "Notice how we use the -->Camel<-- @XPath annotation to grab the data from the XML document (#1)."

2. Listing 9-1 is vulnerable to SQL Injection attacks[1]. If possible, it should be rewritten with parameterized statements.

[1] http://en.wikipedia.org/wiki/SQL_injection

3. p.271, within Figure 9-5, make sure the misspelling of "Receiver" is fixed.
gmazza (30) [Avatar] Offline
#12
Re: Time for your last minute comments
---Chapter 2 Notes

1. In an Camel User's list exchange with Willem[1] I learned that you can't always call getBody() repeatedly (e.g., if the body is an InputStream) and hence may need to change the exchange Body type to a String or something else repeatedly readable if you need to process it further in the route. This is important information that I think that should be mentioned in the book, namely:

(1) what types of Body objects cannot be called repeatedly within process() (primarily just InputStream?) and how we're to check the Body object type (I guess just instanceof()).

(2) Including a mechanism for converting the InputStream into a String or something else that can continue to be processed (read repeatedly further down the route) if needed. Willem gave a couple of solutions in [1].

[1] http://camel.465427.n5.nabble.com/newbie-process-method-eating-Exchange-packet-tp2797348p2797571.html

---Chapter 5 Notes

1. Section 5.4.2, p. 130, "is retrieved from a remote ERP system" -- spell out ERP here as this is the first reference in the book, and you use this term frequently in subsequent chapters.

---Chapter 10 Notes

1. S. 10.1, p. 290: Good to let us know why you're using two routes in Listing 10-1, (.to("direct:update") and then later from("direct:update")) instead of merging the two (placing ".bean(InventoryService.class, "updateInventory");" at the end of the first route. I believe it is just to facilitate the future concurrency examples, but am unsure.

2. S. 10.1, p. 292, Sentence: "The thread pool is by default configured to use 10 threads, which explains why its about 10 times faster." The part "by default" is not clear for me. Can you configure/tweak parallelProcessing() to change the number of threads and perhaps other properties, or do you need to use Custom Thread Pool if you want to do that? If the former, best to provide some info on how to configure parallelProcessing(); if the latter, to replace "is by default configured" to "is hardcoded".

3. Intro of Sect. 10.2, p. 295. I'm having trouble tying your thread pool discussion in 10.2 to the concurrency discussion of 10.1 because I'm unsure which of the three concurrency methods given in 10.1--parallelProcessing(), custom thread pool, SEDA--this thread pool discussion covers. It would be great in the Intro paragraph to 10.2 you state this directly--"this is how the custom thread pool can be maintained..." *or* "the discussions in this section cover all three concurrency methods..." or whatever is the case so we can more easily follow along.
gmazza (30) [Avatar] Offline
#13
Re: Time for your last minute comments
OK, I quickly went through the last four chapters of the book and have no additional comments.
davsclaus (413) [Avatar] Offline
#14
Re: Time for your last minute comments
Thanks for all the feedback and writing the review as well.

We will sure take your comments into account when we go over the chapters during the current production phase.