Note that JAnsi includes the class org.fusesource.jansi.AnsiRenderer which converts strings like "@|bold,red Warning!|@" into ANSI equivalents where @| and |@ are special markers but this is not what I want. I want to have _style_ name a la CSS so I can say "@|warning Your pants are on fire|@" and define "warning" as whatever in the Log4j config.
Gary On Sat, Jun 25, 2016 at 3:09 PM, Gary Gregory <[email protected]> wrote: > Rambling thoughts: > > I use the term message as the message string from the log event (probably > after parameters has been processed.) > > - Add to PatternLayout a %ansiMessage, use that instead of %m and the > layout will rewrite the message as an ANSI message. Use that on a file > layout and you get ANSI codes in your file. > - Add to PatternLayout a %htmlMessage, use that instead of %m and the > layout will rewrite the message as an HTML fragment. The produced HTML > would not be a whole HTML document, just a fragment that fits in an HTML > page/ > > More general: > > Add to PatternLayout a %styledMessage, use that instead of %m and: > - A console appends rewrites the message as an ANSI message. > - An HTML layout rewrites the message as an HTML fragment. > > The message syntax is TDB. > > My focus in on the console appender but thinking about HTML as well helps > consider a more general solution (I hope). > > Gary > > > > On Sat, Jun 25, 2016 at 2:51 PM, Paul Benedict <[email protected]> > wrote: > >> Do you guys have a policy like HTML for ignoring unknown tags/styles when >> parsing a message? So if a message is, for example, "Hey {%s color:red}", >> and the formatter doesn't support colors, it completely ignores the >> "color:red" token? I am implying a backward and forward compatibility. >> >> Cheers, >> Paul >> >> On Sat, Jun 25, 2016 at 2:16 PM, Gary Gregory <[email protected]> >> wrote: >> >>> I meant something like (b). I used the word "render" to try to convey a >>> different concept form "formatting" a message with its parameter. An >>> appender knows how to render a formatted message on itself. >>> >>> The question is how to get no styles on certain appenders and layouts >>> seem to be one good place to do it if I set up that layout for just the one >>> appender that needs it. >>> >>> Gary >>> ? >>> >>> Every appender accepts a Layout for rendering and they all use one. A >>> File appender can use a Pattern layout, a JSON layout, etc. So it is >>> incorrect to say any appender wants no rendering. >>> >>> I think what you are really wanting is a way to either a) enhance the >>> Message.getFormattedMessage() to process the styles in accordance with the >>> Appender type or b) have the Appender process the styles after >>> getFormattedMessage() is called. Architecturally, I like the idea of having >>> the Message handle it but it may be harder to implement. >>> >>> Ralph >>> >>> >>> On Jun 24, 2016, at 12:22 PM, Gary Gregory <[email protected]> >>> wrote: >>> >>> Since an HTML layout and a Console JAnsi layout need different >>> interpretation of the message string, why not allow each appender to do its >>> own rendering? Also, you want no rendering for other appenders like file, >>> JMS, and so on. >>> >>> Gary >>> On Jun 24, 2016 11:07 AM, "Ralph Goers" <[email protected]> >>> wrote: >>> >>>> Yes. Of course the converter would need to be aware what the target is, >>>> which I am not sure is currently available. In this case I would think you >>>> would want to just enhance the %m converter to support these new plugins, >>>> rather than creating a new message converter. >>>> >>>> If you didn’t want to have the output formatted differently depending >>>> on the target I could see having the formatting being done in the Message. >>>> >>>> Ralph >>>> >>>> On Jun 24, 2016, at 10:37 AM, Gary Gregory <[email protected]> >>>> wrote: >>>> >>>> Thank you for the feedback. >>>> >>>> I can see that I could invent a new kind of %m converter that parses >>>> the message and does the coloring. I could have an ANSI kind of %m, an HTML >>>> %m, and so on. >>>> >>>> Gary >>>> On Jun 24, 2016 10:00 AM, "Ralph Goers" <[email protected]> >>>> wrote: >>>> >>>>> >>>>> I am not sure I get this idea at all. First, I would expect that >>>>> “styles” would be plugins much as converters are for the PatternLayout. >>>>> But >>>>> it isn’t clear to me at all why I would want or require a StyledMessage to >>>>> do that. If you want to support “styles” then implement the support in >>>>> the >>>>> appropriate layouts. The message should just contain the information the >>>>> styles need to render them. >>>>> >>>>> Also, is StyledMessage an Interface? If it is a class is it a >>>>> ParameterizedMessage, SimpleMessage, etc, or are you planning on having a >>>>> “Styled” version of each Message type. I am not in favor of that at all. >>>>> >>>>> I am also not sure how this handles the issue you mentioned at the >>>>> start of this thread - that the color codes written to files don’t cause >>>>> the colors to show up and only render properly on the console. >>>>> >>>>> Ralph >>>>> >>>>> On Jun 24, 2016, at 8:43 AM, Gary Gregory <[email protected]> >>>>> wrote: >>>>> >>>>> Another question is what should the syntax be for a StyledMessage? The >>>>> same as for a pattern layout ( >>>>> https://logging.apache.org/log4j/2.x/manual/layouts.html#PatternLayout)? >>>>> Something else? Could it be simpler and still allow for parameters and >>>>> escaping? >>>>> >>>>> SyledMessageFactory factory = SyledMessageFactory.load( ...styles... ); >>>>> item = "pants"; >>>>> // Using pattern layout kind of format with parameter markers. >>>>> logger.error("Your {} are on {fire!}{criticalMassStyle}, >>>>> {notifying}{peacfulStyle}{}", item); >>>>> logger.error("Your %s are on {fire!}{criticalMassStyle}, >>>>> {notifying}{peacfulStyle}%s", item); >>>>> >>>>> Gary >>>>> >>>>> On Tue, Jun 21, 2016 at 6:39 PM, Remko Popma <[email protected]> >>>>> wrote: >>>>> >>>>>> After thinking about it some more, I agree with you guys that the >>>>>> string syntax seems like a better idea. >>>>>> >>>>>> >>>>>> On Wednesday, 22 June 2016, Gary Gregory <[email protected]> >>>>>> wrote: >>>>>> >>>>>>> On Mon, Jun 20, 2016 at 4:14 PM, Remko Popma <[email protected]> >>>>>>> wrote: >>>>>>> >>>>>>>> What if we keep the same or similar syntax but with Log4j2 imports, >>>>>>>> and we use it to build a custom Message? >>>>>>>> >>>>>>>> So, this java code logger.info(ansi().fg(RED).a("Hello").fg(CYAN).a(" >>>>>>>> World").reset()); >>>>>>>> would result in a JansiMessage containing a "Hello" string >>>>>>>> associated with a RED object, and a " World" string associated with the >>>>>>>> CYAN object. At this stage, nothing is rendered yet. >>>>>>>> >>>>>>> >>>>>>> I would prefer to avoid a vendor specific message class and name. I >>>>>>> think the Maven folks are experiencing growing pains now that they have >>>>>>> enabled color within Maven messages. I think a StyledMessage would be >>>>>>> the >>>>>>> way to go. >>>>>>> >>>>>>> When a StyledMessage goes to a Console appender, JAnsi is used, when >>>>>>> it does to an HTML appender, HTML is used. Whether you build a >>>>>>> StyledMessage with a fluent API, a string syntax or both is another >>>>>>> matter, >>>>>>> but the string syntax seems simplest. >>>>>>> >>>>>>> Gary >>>>>>> >>>>>>> >>>>>>>> The Console Appender's PatternLayout, when the Jansi option is >>>>>>>> enabled, could call JansiMessage.generateJansiFormattedMessage() which >>>>>>>> contains the escape codes for the console. >>>>>>>> >>>>>>>> The File Appender's PatternLayout does not have the Jansi option >>>>>>>> enabled, so the normal Message.getFormattedMessage() is called, >>>>>>>> resulting >>>>>>>> in the plain string "Hello World". >>>>>>>> >>>>>>>> One key consideration is that all the objects used to build the >>>>>>>> message should be in the Log4j API namespace to avoid any dependency on >>>>>>>> Jansi at the API level. (But things like RED etc can be inner classes >>>>>>>> of >>>>>>>> JansiMessage. Static imports can make this painless to use.) >>>>>>>> >>>>>>>> >>>>>>>> On Tue, Jun 21, 2016 at 3:59 AM, Paul Benedict < >>>>>>>> [email protected]> wrote: >>>>>>>> >>>>>>>>> It's pretty cool. Yes, a generalized syntax is very nice. Do your >>>>>>>>> best to make the syntax general -- and if for, for whatever reason, an >>>>>>>>> appender needs something more explicit/specific, those options can >>>>>>>>> just be >>>>>>>>> provided by the appender's custom parsing. >>>>>>>>> >>>>>>>>> Cheers, >>>>>>>>> Paul >>>>>>>>> >>>>>>>>> On Mon, Jun 20, 2016 at 1:44 PM, Gary Gregory < >>>>>>>>> [email protected]> wrote: >>>>>>>>> >>>>>>>>>> I think like the idea of having a special syntax for colors, for >>>>>>>>>> rendering of styles in general actually, because we could have this >>>>>>>>>> implemented for the Jansi+Console appender, for the HTML appender, >>>>>>>>>> and you >>>>>>>>>> could also imagine an RTF appender. >>>>>>>>>> >>>>>>>>>> Gary >>>>>>>>>> >>>>>>>>>> On Thu, Jun 16, 2016 at 12:59 PM, Gary Gregory < >>>>>>>>>> [email protected]> wrote: >>>>>>>>>> >>>>>>>>>>> On Thu, Jun 16, 2016 at 12:48 PM, Paul Benedict < >>>>>>>>>>> [email protected]> wrote: >>>>>>>>>>> >>>>>>>>>>>> I imagine parsing the placeholder is going to be expensive >>>>>>>>>>>> (relatively speaking). It is an extra cost. >>>>>>>>>>>> >>>>>>>>>>> >>>>>>>>>>> We already support different ways to paramaterize messages [1]: >>>>>>>>>>> {}, %s (and family), java.text.MessageFormat, and so on. Each has >>>>>>>>>>> its >>>>>>>>>>> different overhead. >>>>>>>>>>> >>>>>>>>>>> This could be a variation of the ParameterizedMessage class for >>>>>>>>>>> example. Or maybe an extension of to one or more other message >>>>>>>>>>> types. >>>>>>>>>>> >>>>>>>>>>> Gary >>>>>>>>>>> >>>>>>>>>>> [1] https://logging.apache.org/log4j/2.x/manual/messages.html >>>>>>>>>>> >>>>>>>>>>> >>>>>>>>>>>> I advise devising a new interface that appenders can implement >>>>>>>>>>>> to receive the parsed tokens. If the interface is missing, no >>>>>>>>>>>> parsing >>>>>>>>>>>> in-between is necessary. Otherwise, send the tokens to the >>>>>>>>>>>> appender as a >>>>>>>>>>>> callback for it to make the necessary modifications -- such as >>>>>>>>>>>> setting the >>>>>>>>>>>> color. >>>>>>>>>>>> >>>>>>>>>>>> Cheers, >>>>>>>>>>>> Paul >>>>>>>>>>>> >>>>>>>>>>>> On Thu, Jun 16, 2016 at 1:53 PM, Gary Gregory < >>>>>>>>>>>> [email protected]> wrote: >>>>>>>>>>>> >>>>>>>>>>>>> >>>>>>>>>>>>> On Jun 16, 2016 11:25 AM, "Paul Benedict" < >>>>>>>>>>>>> [email protected]> wrote: >>>>>>>>>>>>> > >>>>>>>>>>>>> > Are you asking me for blue sky thinking, perhaps something >>>>>>>>>>>>> like this: >>>>>>>>>>>>> > log.info("Hello, {color:green}, how are you?", "Gary"); >>>>>>>>>>>>> > >>>>>>>>>>>>> > For this example, I took the {} placeholder and added some >>>>>>>>>>>>> context. >>>>>>>>>>>>> >>>>>>>>>>>>> Ok yes, that's what I was talking about. Also: >>>>>>>>>>>>> >>>>>>>>>>>>> log.info("Hello {color:green Gary}, how are you?"); >>>>>>>>>>>>> >>>>>>>>>>>>> Gary >>>>>>>>>>>>> > >>>>>>>>>>>>> > Cheers, >>>>>>>>>>>>> > Paul >>>>>>>>>>>>> > >>>>>>>>>>>>> > On Thu, Jun 16, 2016 at 1:22 PM, Gary Gregory < >>>>>>>>>>>>> [email protected]> wrote: >>>>>>>>>>>>> >> >>>>>>>>>>>>> >> On Thu, Jun 16, 2016 at 11:04 AM, Paul Benedict < >>>>>>>>>>>>> [email protected]> wrote: >>>>>>>>>>>>> >>> >>>>>>>>>>>>> >>> I think color falls into the category of formatting. By >>>>>>>>>>>>> that, I mean to state that colors shouldn't be hardcoded into >>>>>>>>>>>>> messages :-) >>>>>>>>>>>>> That should belong to the actual formatter... template string or >>>>>>>>>>>>> appender >>>>>>>>>>>>> configuration. >>>>>>>>>>>>> >> >>>>>>>>>>>>> >> >>>>>>>>>>>>> >> What would that look like? I do not see how do to that >>>>>>>>>>>>> without creating a lot of custom code. >>>>>>>>>>>>> >> >>>>>>>>>>>>> >> Gary >>>>>>>>>>>>> >> >>>>>>>>>>>>> >>> >>>>>>>>>>>>> >>> >>>>>>>>>>>>> >>> Cheers, >>>>>>>>>>>>> >>> Paul >>>>>>>>>>>>> >>> >>>>>>>>>>>>> >>> On Thu, Jun 16, 2016 at 12:58 PM, Gary Gregory < >>>>>>>>>>>>> [email protected]> wrote: >>>>>>>>>>>>> >>>> >>>>>>>>>>>>> >>>> On Thu, Jun 16, 2016 at 10:39 AM, Gary Gregory < >>>>>>>>>>>>> [email protected]> wrote: >>>>>>>>>>>>> >>>>> >>>>>>>>>>>>> >>>>> On Wed, Jun 15, 2016 at 10:50 PM, Gary Gregory < >>>>>>>>>>>>> [email protected]> wrote: >>>>>>>>>>>>> >>>>>> >>>>>>>>>>>>> >>>>>> Hi All, >>>>>>>>>>>>> >>>>>> >>>>>>>>>>>>> >>>>>> See color messages in Maven 3.4.0-SNAPSHOT made me >>>>>>>>>>>>> think of the following. >>>>>>>>>>>>> >>>>>> >>>>>>>>>>>>> >>>>>> Right now, with Jansi on the CP, I can say: >>>>>>>>>>>>> >>>>>> >>>>>>>>>>>>> >>>>>> import static org.fusesource.jansi.Ansi.*; >>>>>>>>>>>>> >>>>>> import static org.fusesource.jansi.Ansi.Color.*; >>>>>>>>>>>>> >>>>>> ... >>>>>>>>>>>>> >>>>>> logger.info(ansi().fg(RED).a("Hello").fg(CYAN).a(" >>>>>>>>>>>>> World").reset()); >>>>>>>>>>>>> >>>>>> >>>>>>>>>>>>> >>>>>> and the right thing happens on the console. >>>>>>>>>>>>> >>>>>> >>>>>>>>>>>>> >>>>>> If I also have a file appender, I get the escape codes >>>>>>>>>>>>> in the file, which I do not think most people would want. >>>>>>>>>>>>> >>>>>> >>>>>>>>>>>>> >>>>>> The question is, how can we make it simple for users to >>>>>>>>>>>>> have their cake and eat it too? >>>>>>>>>>>>> >>>>>> >>>>>>>>>>>>> >>>>>> With a special Message implementation? >>>>>>>>>>>>> >>>>>> >>>>>>>>>>>>> >>>>>> Thoughts? >>>>>>>>>>>>> >>>>> >>>>>>>>>>>>> >>>>> >>>>>>>>>>>>> >>>>> One way would be to have the non-a() methods (plus >>>>>>>>>>>>> reset()) become no-ops when not using a console appender. But >>>>>>>>>>>>> how? We could >>>>>>>>>>>>> have a subclass of JAnsi's Ansi class that gets used. Anyway, I'm >>>>>>>>>>>>> just >>>>>>>>>>>>> rambling. >>>>>>>>>>>>> >>>> >>>>>>>>>>>>> >>>> >>>>>>>>>>>>> >>>> Still rambling, mostly so I have a place to look back for >>>>>>>>>>>>> these notes: >>>>>>>>>>>>> >>>> >>>>>>>>>>>>> >>>> - nope, the reset() method would need to be noop'd. >>>>>>>>>>>>> >>>> - Example of a color message: >>>>>>>>>>>>> org.apache.logging.log4j.core.appender.ConsoleAppenderJAnsiMessageMain >>>>>>>>>>>>> >>>> - JAnsi also supports a special syntax, for example: >>>>>>>>>>>>> >>>> >>>>>>>>>>>>> >>>> "@|red Hello|@ @|cyan World|@" >>>>>>>>>>>>> >>>> >>>>>>>>>>>>> >>>> but if use that like: >>>>>>>>>>>>> >>>> >>>>>>>>>>>>> >>>> logger.info("@|red Hello|@ @|cyan World|@"); >>>>>>>>>>>>> >>>> >>>>>>>>>>>>> >>>> JAnsi rendering does not kick in unsurprisingly. >>>>>>>>>>>>> >>>> >>>>>>>>>>>>> >>>> Maybe the Console appender could make sure the JAnsi >>>>>>>>>>>>> renderer is used (optional), so that >>>>>>>>>>>>> >>>> >>>>>>>>>>>>> >>>> logger.info(ansi().render("@|red Hello|@ @|green >>>>>>>>>>>>> World|@"); >>>>>>>>>>>>> >>>> >>>>>>>>>>>>> >>>> can become: >>>>>>>>>>>>> >>>> >>>>>>>>>>>>> >>>> logger.info("@|red Hello|@ @|green World|@"); >>>>>>>>>>>>> >>>> >>>>>>>>>>>>> >>>> and then we can add a renderJansi option to the console >>>>>>>>>>>>> appender but... the decorations still end up in a file appender >>>>>>>>>>>>> so we are >>>>>>>>>>>>> still in the same pickle. >>>>>>>>>>>>> >>>> >>>>>>>>>>>>> >>>> Thinking about a MessageRenderer (String render(String)) >>>>>>>>>>>>> interface with two impl: one that calls ansi().render(String) for >>>>>>>>>>>>> console >>>>>>>>>>>>> appenders (optionally, if renderJansi=true) and another that >>>>>>>>>>>>> strips the >>>>>>>>>>>>> decorations (but this feels heavy). >>>>>>>>>>>>> >>>> >>>>>>>>>>>>> >>>> More rambling: >>>>>>>>>>>>> >>>> >>>>>>>>>>>>> >>>> Instead of: >>>>>>>>>>>>> >>>> >>>>>>>>>>>>> >>>> logger.info(ansi().fg(RED).a("Hello").fg(CYAN).a(" >>>>>>>>>>>>> World").reset()); >>>>>>>>>>>>> >>>> >>>>>>>>>>>>> >>>> say: >>>>>>>>>>>>> >>>> >>>>>>>>>>>>> >>>> logger.info((Ansi ansi) -> >>>>>>>>>>>>> ansi.fg(RED).a("Hello").fg(CYAN).a(" World").reset()); >>>>>>>>>>>>> >>>> >>>>>>>>>>>>> >>>> Then we can pass in a custom Ansi subclass that only >>>>>>>>>>>>> outputs the string bits, no escape codes. >>>>>>>>>>>>> >>>> >>>>>>>>>>>>> >>>> Gary >>>>>>>>>>>>> >>>> >>>>>>>>>>>>> >>>>> >>>>>>>>>>>>> >>>>> Gary >>>>>>>>>>>>> >>>>> >>>>>>>>>>>>> >>>>>> >>>>>>>>>>>>> >>>>>> Thank you, >>>>>>>>>>>>> >>>>>> Gary >>>>>>>>>>>>> >>>>>> -- >>>>>>>>>>>>> >>>>>> E-Mail: [email protected] | [email protected] >>>>>>>>>>>>> >>>>>> Java Persistence with Hibernate, Second Edition >>>>>>>>>>>>> >>>>>> JUnit in Action, Second Edition >>>>>>>>>>>>> >>>>>> Spring Batch in Action >>>>>>>>>>>>> >>>>>> Blog: http://garygregory.wordpress.com >>>>>>>>>>>>> >>>>>> Home: http://garygregory.com/ >>>>>>>>>>>>> >>>>>> Tweet! http://twitter.com/GaryGregory >>>>>>>>>>>>> >>>>> >>>>>>>>>>>>> >>>>> >>>>>>>>>>>>> >>>>> >>>>>>>>>>>>> >>>>> >>>>>>>>>>>>> >>>>> -- >>>>>>>>>>>>> >>>>> E-Mail: [email protected] | [email protected] >>>>>>>>>>>>> >>>>> Java Persistence with Hibernate, Second Edition >>>>>>>>>>>>> >>>>> JUnit in Action, Second Edition >>>>>>>>>>>>> >>>>> Spring Batch in Action >>>>>>>>>>>>> >>>>> Blog: http://garygregory.wordpress.com >>>>>>>>>>>>> >>>>> Home: http://garygregory.com/ >>>>>>>>>>>>> >>>>> Tweet! http://twitter.com/GaryGregory >>>>>>>>>>>>> >>>> >>>>>>>>>>>>> >>>> >>>>>>>>>>>>> >>>> >>>>>>>>>>>>> >>>> >>>>>>>>>>>>> >>>> -- >>>>>>>>>>>>> >>>> E-Mail: [email protected] | [email protected] >>>>>>>>>>>>> >>>> Java Persistence with Hibernate, Second Edition >>>>>>>>>>>>> >>>> JUnit in Action, Second Edition >>>>>>>>>>>>> >>>> Spring Batch in Action >>>>>>>>>>>>> >>>> Blog: http://garygregory.wordpress.com >>>>>>>>>>>>> >>>> Home: http://garygregory.com/ >>>>>>>>>>>>> >>>> Tweet! http://twitter.com/GaryGregory >>>>>>>>>>>>> >>> >>>>>>>>>>>>> >>> >>>>>>>>>>>>> >> >>>>>>>>>>>>> >> >>>>>>>>>>>>> >> >>>>>>>>>>>>> >> -- >>>>>>>>>>>>> >> E-Mail: [email protected] | [email protected] >>>>>>>>>>>>> >> Java Persistence with Hibernate, Second Edition >>>>>>>>>>>>> >> JUnit in Action, Second Edition >>>>>>>>>>>>> >> Spring Batch in Action >>>>>>>>>>>>> >> Blog: http://garygregory.wordpress.com >>>>>>>>>>>>> >> Home: http://garygregory.com/ >>>>>>>>>>>>> >> Tweet! http://twitter.com/GaryGregory >>>>>>>>>>>>> > >>>>>>>>>>>>> > >>>>>>>>>>>>> >>>>>>>>>>>> >>>>>>>>>>>> >>>>>>>>>>> >>>>>>>>>>> >>>>>>>>>>> -- >>>>>>>>>>> E-Mail: [email protected] | [email protected] >>>>>>>>>>> Java Persistence with Hibernate, Second Edition >>>>>>>>>>> <http://www.manning.com/bauer3/> >>>>>>>>>>> JUnit in Action, Second Edition >>>>>>>>>>> <http://www.manning.com/tahchiev/> >>>>>>>>>>> Spring Batch in Action <http://www.manning.com/templier/> >>>>>>>>>>> Blog: http://garygregory.wordpress.com >>>>>>>>>>> Home: http://garygregory.com/ >>>>>>>>>>> Tweet! http://twitter.com/GaryGregory >>>>>>>>>>> >>>>>>>>>> >>>>>>>>>> >>>>>>>>>> >>>>>>>>>> -- >>>>>>>>>> E-Mail: [email protected] | [email protected] >>>>>>>>>> Java Persistence with Hibernate, Second Edition >>>>>>>>>> <http://www.manning.com/bauer3/> >>>>>>>>>> JUnit in Action, Second Edition >>>>>>>>>> <http://www.manning.com/tahchiev/> >>>>>>>>>> Spring Batch in Action <http://www.manning.com/templier/> >>>>>>>>>> Blog: http://garygregory.wordpress.com >>>>>>>>>> Home: http://garygregory.com/ >>>>>>>>>> Tweet! http://twitter.com/GaryGregory >>>>>>>>>> >>>>>>>>> >>>>>>>>> >>>>>>>> >>>>>>> >>>>>>> >>>>>>> -- >>>>>>> E-Mail: [email protected] | [email protected] >>>>>>> Java Persistence with Hibernate, Second Edition >>>>>>> <http://www.manning.com/bauer3/> >>>>>>> JUnit in Action, Second Edition <http://www.manning.com/tahchiev/> >>>>>>> Spring Batch in Action <http://www.manning.com/templier/> >>>>>>> Blog: http://garygregory.wordpress.com >>>>>>> Home: http://garygregory.com/ >>>>>>> Tweet! http://twitter.com/GaryGregory >>>>>>> >>>>>> >>>>> >>>>> >>>>> -- >>>>> E-Mail: [email protected] | [email protected] >>>>> Java Persistence with Hibernate, Second Edition >>>>> <http://www.manning.com/bauer3/> >>>>> JUnit in Action, Second Edition <http://www.manning.com/tahchiev/> >>>>> Spring Batch in Action <http://www.manning.com/templier/> >>>>> Blog: http://garygregory.wordpress.com >>>>> Home: http://garygregory.com/ >>>>> Tweet! http://twitter.com/GaryGregory >>>>> >>>>> >>>>> >>>> >>> >> > > > -- > E-Mail: [email protected] | [email protected] > Java Persistence with Hibernate, Second Edition > <http://www.manning.com/bauer3/> > JUnit in Action, Second Edition <http://www.manning.com/tahchiev/> > Spring Batch in Action <http://www.manning.com/templier/> > Blog: http://garygregory.wordpress.com > Home: http://garygregory.com/ > Tweet! http://twitter.com/GaryGregory > -- E-Mail: [email protected] | [email protected] Java Persistence with Hibernate, Second Edition <http://www.manning.com/bauer3/> JUnit in Action, Second Edition <http://www.manning.com/tahchiev/> Spring Batch in Action <http://www.manning.com/templier/> Blog: http://garygregory.wordpress.com Home: http://garygregory.com/ Tweet! http://twitter.com/GaryGregory
