tag:blogger.com,1999:blog-6007315848648081942024-03-14T07:15:49.570+01:00IT is a state of mindTechnology blog by Tomasz PrzybyszUnknownnoreply@blogger.comBlogger9125tag:blogger.com,1999:blog-600731584864808194.post-10973253314233103702016-10-01T13:27:00.002+02:002016-10-01T16:02:52.901+02:00How to easily avoid switch-case statement with function mapping in JavaScriptI won't advertise why it's good to avoid <span style="font-family: "courier new" , "courier" , monospace;">switch-case</span>. While this matter might still be an open dispute I think there are usually better ways to implement what a <span style="font-family: "courier new" , "courier" , monospace;">switch-case</span> does.<br />
<br />
My vote would go for <i>polymorphism</i>, unfortunately much JavaScript code out there is not written following good OOP principles. So if you just need to work with given code base but not making a revolution there is a neat way to go:<br />
<pre class="default prettyprint prettyprinted brush:javascript">const actions = {
value1: actionX,
value2: actionY,
value3: actionZ
};
actions[value]();</pre>Where action <i>X</i>, <i>Y</i>, <i>Z</i> are functions.<br />
<br />
Of course it's good to add some check for <span style="font-family: "courier new" , "courier" , monospace;">undefined</span> <i>value</i>, like:<br />
<pre class="default prettyprint prettyprinted brush:javascript">actions[value] && actions[value]();</pre><br />
Or an error might be thrown if no mapping found as follows:<br />
<pre class="default prettyprint prettyprinted brush:javascript">const action = actions[value]
? actions[value]
: (value) => throw new Error('No action mapped for value: ' + value);
action(value);</pre>Well, that's it. I believe it helps to reduce clutter in code. Just compare it to a typical switch:<br />
<pre class="default prettyprint prettyprinted brush:javascript">switch (value) {
case 'value1':
actionX();
break;
case 'value2':
actionY();
break;
case 'value3':
actionZ();
break;
default: throw new Error('No action mapped for value: ' + value)
}</pre><br />
<br />
Exactly the same idea can be done in Groovy, Java and other languages if you are not up for polymorphism on a given case. Although for some languages with no functional paradigm, like Java before version 8, you may need to create some sort of <i>Action</i> class definition.Unknownnoreply@blogger.com6tag:blogger.com,1999:blog-600731584864808194.post-58515569786334304822016-10-01T13:27:00.001+02:002016-10-01T15:59:40.199+02:00How to easily avoid switch-case statement with function mapping in JavaScriptI won't advertise why it's good to avoid <span style="font-family: "courier new" , "courier" , monospace;">switch-case</span>. While this matter might still be an open dispute I think there are usually better ways to implement what a <span style="font-family: "courier new" , "courier" , monospace;">switch-case</span> does.<br />
<br />
My vote would go for <i>polymorphism</i>, unfortunately much JavaScript code out there is not written following good OOP principles. So if you just need to work with given code base but not making a revolution there is a neat way to go:<br />
<pre class="default prettyprint prettyprinted brush:javascript">const actions = {
value1: actionX,
value2: actionY,
value3: actionZ
};
actions[value]();</pre>Where action <i>X</i>, <i>Y</i>, <i>Z</i> are functions.<br />
<br />
Of course it's good to add some check for <span style="font-family: "courier new" , "courier" , monospace;">undefined</span> <i>value</i>, like:<br />
<pre class="default prettyprint prettyprinted brush:javascript">actions[value] && actions[value]();</pre><br />
Or an error might be thrown if no mapping found as follows:<br />
<pre class="default prettyprint prettyprinted brush:javascript">const action = actions[value]
? actions[value]
: (value) => throw new Error('No action mapped for value: ' + value);
action(value);</pre>Well, that's it. I believe it helps to reduce clutter in code if you compare it to something like:<br />
<pre class="default prettyprint prettyprinted brush:javascript">switch (value) {
case 'value1':
actionX();
break;
case 'value2':
actionY();
break;
case 'value3':
actionZ();
break;
default: throw new Error('No action mapped for value: ' + value)
}</pre><br />
Exactly the same can be done in Groovy, Java and other languages if you are not up for polymorphism on a given case. Although for some languages with no functional paradigm, like Java before version 8, you may need to create some sort of <i>Action</i> class definition.Unknownnoreply@blogger.com3tag:blogger.com,1999:blog-600731584864808194.post-79625537341155625012015-10-12T23:34:00.000+02:002015-10-12T23:55:56.525+02:00Static vs dynamic method overloading with Java and GroovyGroovy code may be quite similar to Java at the first glimpse. This may sometimes lead to caveats. A good example of such is method overloading by an argument type. Code may look the same in both languages but it's going to work different.<br />
<h2>Example</h2>Consider the following class:<br />
<br />
<pre class="default prettyprint prettyprinted brush:java">public class Foo {
public String bar(Object value) {
return "Object: " + value;
}
public String bar(String value) {
return "String: " + value;
}
public String bar(Integer value) {
return "Integer: " + value;
}
}</pre><br />
Although it's a Java class it doesn't really matter at this point whether it's Groovy or Java. The caller class matters.<br />
<h2>JAVA: static binding for overloaded methods</h2>Caller class written in Java:<br />
<pre class="default prettyprint prettyprinted brush:java">public class StaticBindingExample {
public static void main(String[] args) {
Object number = 44;
Object text = "plop!";
Foo foo = new Foo();
foo.bar(number); // returns "Object: 44"
foo.bar(text); // returns "Object: plop!"
}
}</pre>By Java static nature, calling the <tt>bar()</tt> method always invokes the one which signature matches the argument declared type.<br />
<h2>Groovy: dynamic binding for method overloading</h2>That's the exact same code for caller class as in the previous snippet just written in Groovy:<br />
<pre class="default prettyprint prettyprinted brush:groovy">class DynamicBindingExample {
static void main(String[] args) {
Object number = 44
Object text = 'plop!'
Foo foo = new Foo()
foo.bar(number) // returns "Integer: 44"
foo.bar(text) // returns "String: plop!"
}
}</pre>Here we can see the difference. Despite the arguments for the method call were declared as <tt>Object</tt>, Groovy dynamic type evaluation always tries to match the closest matching method at runtime. Thus methods relevant for the actual argument type were executed.<br />
<h2>Advantage of dynamic binding</h2>Please consider an example of some payment service written in Java:<br />
<pre class="default prettyprint prettyprinted brush:java">public class PaymentService {
private final CustomerRepository customerRepository;
private final AccountService accountService;
public PaymentService(CustomerRepository customerRepository, AccountService accountService) {
this.customerRepository = customerRepository;
this.accountService = accountService;
}
public void pay(Integer customerId, BigDecimal amount) {
Customer customer = customerRepository.findById(customerId); // may throw UnknownCustomerException
accountService.substract(customer, amount); // may throw InsufficientFundsException
}
}</pre>How is going to look exception handling if we add <tt>try-catch</tt> block around business logic within the <tt>pay()</tt> method? Well, quite typical:<br />
<pre class="default prettyprint prettyprinted brush:java">public void pay(Integer customerId, BigDecimal amount) {
try {
Customer customer = customerRepository.findById(customerId); // may throw UnknownCustomerException
accountService.substract(customer, amount); // may throw InsufficientFundsException
} catch (UnknownCustomerException ex) {
handle(ex);
} catch (InsufficientFundsException ex) {
handle(ex);
} catch (Exception ex) {
handle(ex);
}
}
private void handle(UnknownCustomerException ex) {
// relevant logic for handling unknown customer
}
private void handle(InsufficientFundsException ex) {
// relevant logic for handling insufficient funds
}
private void handle(Exception ex) {
// relevant logic for handling unexpected exception
}</pre>Obviously if the handling logic isn't complex, delegation to separate methods may be skipped in favour of in-line handling inside of each <tt>catch</tt> block. Although splitting the logic into methods or encapsulating exception handling in injected collaborator is usually a better way and cleaner separation of concerns.<br />
<br />
This way or the other we may see straight away that <tt>catch</tt> blocks are rather redundant in this situation. How would it look like with Groovy's dynamic overloading? It’s enough to have single, generic type, <tt>catch</tt> block. Invocation is routed to appropriate <tt>handle()</tt> method by the argument type anyway:<br />
<pre class="default prettyprint prettyprinted brush:groovy">void pay(Integer customerId, BigDecimal amount) {
try {
Customer customer = customerRepository.findById(customerId) // may throw UnknownCustomerException
accountService.substract(customer, amount) // may throw InsufficientFundsException
} catch (Exception ex) {
handle(ex)
}
}
private void handle(UnknownCustomerException ex) {
// relevant logic for handling unknown customer
}
private void handle(InsufficientFundsException ex) {
// relevant logic for handling insufficient funds
}
private void handle(Exception ex) {
// relevant logic for handling unexpected exception
}</pre>The same implemented with the less amount of a cleaner code? That's what a craftsman appreciates.<br />
<h2>The same behaviour with Java static overloading</h2>There is a way to achieve "the same" with pure Java, the <a href="https://today.java.net/article/2010/04/26/match-maker-design-pattern-new-place-actions">Match Maker Design Pattern</a>. I'm not sure about the name of the pattern itself though. I've got the feeling that Martin Fowler, Gang of Four or some other guru might have come with a better definition for such a case. I can't find it at the moment so let’s get back to the code (you're welcome to comment if you know it though).<br />
<br />
Simply we may have a "routing" map of class type to be handled to the handler for it. In our case it can be done by adding mentioned map as the <tt>PaymentService</tt> class field and then using it in the catch block as follows. Let say the handlers map is injected via constructor then we simple have a few more lines of code:<br />
<pre class="default prettyprint prettyprinted brush:java">public class PaymentService {
// …
private final Map<Class<? extends Exception>, ExceptionHandler> handlers;
public PaymentService(CustomerRepository customerRepository, AccountService accountService,
Map<Class<? extends Exception>, ExceptionHandler> handlers) {
// …
this.handlers = handlers;
}
public void pay(Integer customerId, BigDecimal amount) {
try {
// …
} catch (Exception ex) {
ExceptionHandler handler = handlers.get(ex.getClass());
handler.handle(ex);
}
}
}</pre>Obviously we need the handler interface as well, nothing surprising here:<br />
<pre class="default prettyprint prettyprinted brush:java">interface ExceptionHandler {
public void handle(Exception ex)
}</pre>That's it, isn't it? Well, not quite, to be honest. To get the proper impression of how much more code actually is necessary the best way is to show the complete example. If we were about to encapsulate the same, full logic within a single class it would look like:<br />
<pre class="default prettyprint prettyprinted brush:java">public class PaymentService {
private final CustomerRepository customerRepository;
private final AccountService accountService;
private final Map<Class<? extends Exception>, ExceptionHandler> handlers;
public PaymentService(CustomerRepository customerRepository, AccountService accountService,
Map<Class<? extends Exception>, ExceptionHandler> handlers) {
this.customerRepository = customerRepository;
this.accountService = accountService;
this.handlers = createExceptionHandlers();
}
public void pay(Integer customerId, BigDecimal amount) {
try {
Customer customer = customerRepository.findById(customerId); // may throw UnknownCustomerException
accountService.substract(customer, amount); // may throw InsufficientFundsException
} catch (Exception ex) {
ExceptionHandler handler = handlers.get(ex.getClass());
handler.handle(ex);
}
}
private Map<Class<? extends Exception>, ExceptionHandler> createExceptionHandlers() {
HashMap<Class<? extends Exception>, ExceptionHandler> handlers = new HashMap<>();
handlers.put(UnknownCustomerException.class, createUnknownCustomerExceptionHandler());
handlers.put(InsufficientFundsException.class, createInsufficientFundsExceptionHandler());
handlers.put(Exception.class, createUnexpectedExceptionHandler());
return handlers;
}
private ExceptionHandler createUnknownCustomerExceptionHandler() {
return new ExceptionHandler() {
@Override
void handle(Exception ex) {
// relevant logic for handling unknown customer
}
};
}
private ExceptionHandler createInsufficientFundsExceptionHandler() {
return new ExceptionHandler() {
@Override
void handle(Exception ex) {
// relevant logic for handling insufficient funds
}
};
}
private ExceptionHandler createUnexpectedExceptionHandler() {
return new ExceptionHandler() {
@Override
void handle(Exception ex) {
// relevant logic for handling unexpected exception
}
};
}
}</pre><h2>Summary</h2>Clearly solution complexity may grow really fast if one wants to mimic dynamic binding behaviour in a language which by its nature does it the static way. Dynamic method overloading comes then as really helpful thing which allows avoiding unnecessary clutter in the code.<br />
<br />
On the other hand it suits well rather simpler scenarios of dealing with objects from the same inheritance tree. It doesn't have to always be the best approach though. Too much logic placed within a single class is almost never a good idea. As usual the trick is to choose the proper solution for the job as well as the programming language itself.Unknownnoreply@blogger.com1tag:blogger.com,1999:blog-600731584864808194.post-89330987355167960262014-12-31T17:44:00.002+01:002014-12-31T17:57:46.171+01:00Merge multiple log files preserving entries order<h2>Problem</h2>When solving issues occurred in bigger, especially multi-threading or even multi-processes, applications it happens there is a need to work with multiple log files written at the same time.<br />
To get a full view of what's happened in such an app the most convenient would be to have a single log file combined with chronological order of log entries preserved.<br />
<br />
This article shows how to achieve this with just a linux <i>sort</i> command without breaking multi-lines entries (f.g. Java stacktraces).<br />
<h2>Example</h2><div>As my case was almost the same I took below samples from <i>stackoverflow</i> <a href="http://stackoverflow.com/questions/15866772/merging-multiple-log-files-by-date-including-multilines" target="_blank">question</a> (which features my answer as well).<br />
Additionally, I prepended each entry with date to match my case better. This doesn't change anything though.</div><h3>Input</h3><div>To simplify example all log entries are from the same date, hour and minute, but solution works for any date/time log entries.</div><div><br />
</div><b>file1.log</b><br />
<pre style="background-color: #eeeeee; border: 0px; font-family: Consolas, Menlo, Monaco, 'Lucida Console', 'Liberation Mono', 'DejaVu Sans Mono', 'Bitstream Vera Sans Mono', 'Courier New', monospace, serif; font-size: 14px; line-height: 17.804800033569336px; margin-bottom: 10px; max-height: 600px; overflow: auto; padding: 5px; vertical-align: baseline; width: auto; word-wrap: normal;"><code style="border: 0px; font-family: Consolas, Menlo, Monaco, 'Lucida Console', 'Liberation Mono', 'DejaVu Sans Mono', 'Bitstream Vera Sans Mono', 'Courier New', monospace, serif; margin: 0px; padding: 0px; vertical-align: baseline; white-space: inherit;">2014-12-31 11:48:18.825 [main] INFO org.hibernate.cfg.Environment - HHH000206: hibernate.properties not found
<span style="white-space: inherit;">2014-12-31 </span>11:48:55.784 [main] INFO o.h.tool.hbm2ddl.SchemaUpdate - HHH000396: Updating schema</code></pre><br />
<b>file2.log</b><br />
<pre style="background-color: #eeeeee; border: 0px; font-family: Consolas, Menlo, Monaco, 'Lucida Console', 'Liberation Mono', 'DejaVu Sans Mono', 'Bitstream Vera Sans Mono', 'Courier New', monospace, serif; font-size: 14px; line-height: 17.804800033569336px; margin-bottom: 10px; max-height: 600px; overflow: auto; padding: 5px; vertical-align: baseline; width: auto; word-wrap: normal;"><code style="border: 0px; font-family: Consolas, Menlo, Monaco, 'Lucida Console', 'Liberation Mono', 'DejaVu Sans Mono', 'Bitstream Vera Sans Mono', 'Courier New', monospace, serif; margin: 0px; padding: 0px; vertical-align: baseline; white-space: inherit;"><span style="white-space: inherit;">2014-12-31 </span>11:48:35.377 [qtp1484319352-19] ERROR c.w.b.c.ControllerErrorHandler -
org.springframework.beans.TypeMismatchException: Failed to convert value of type 'java.lang.String' to required type 'org.joda.time.LocalDate'; nested exception is org.springframework.core.convert.ConversionFailedException: Failed to convert from type java.lang.String to type @org.springframework.web.bind.annotation.RequestParam @org.springframework.format.annotation.DateTimeFormat org.joda.time.LocalDate for value '[2013-03-26]'; nested exception is java.lang.IllegalArgumentException: Invalid format: " [2013-03-26]"
at org.springframework.beans.TypeConverterSupport.doConvert(TypeConverterSupport.java:68) ~[spring-beans-3.2.1.RELEASE.jar:3.2.1.RELEASE]
at org.springframework.beans.TypeConverterSupport.convertIfNecessary(TypeConverterSupport.java:45) ~[spring-beans-3.2.1.RELEASE.jar:3.2.1.RELEASE]
at org.springframework.validation.DataBinder.convertIfNecessary(DataBinder.java:595) ~[spring-context-3.2.1.RELEASE.jar:3.2.1.RELEASE]
at org.springframework.web.method.annotation.AbstractNamedValueMethodArgumentResolver.resolveArgument(AbstractNamedValueMethodArgumentResolver.java:98) ~[spring-web-3.2.1.RELEASE.jar:3.2.1.RELEASE]
at org.springframework.web.method.support.HandlerMethodArgumentResolverComposite.resolveArgument(HandlerMethodArgumentResolverComposite.java:77) ~[spring-web-3.2.1.RELEASE.jar:3.2.1.RELEASE]
at org.springframework.web.method.support.InvocableHandlerMethod.getMethodArgumentValues(InvocableHandlerMethod.java:162) ~[spring-web-3.2.1.RELEASE]</code></pre><h3>Expected output</h3><div>As you can see to preserve chronological order upon merge entry from file2.log has to get between two entries from file1.log. We want stacktrace to stick with its entry as well.</div><div><br />
</div><div><pre style="background-color: #eeeeee; border: 0px; font-family: Consolas, Menlo, Monaco, 'Lucida Console', 'Liberation Mono', 'DejaVu Sans Mono', 'Bitstream Vera Sans Mono', 'Courier New', monospace, serif; font-size: 14px; line-height: 17.804800033569336px; margin-bottom: 10px; max-height: 600px; overflow: auto; padding: 5px; vertical-align: baseline; width: auto; word-wrap: normal;"><code style="border: 0px; font-family: Consolas, Menlo, Monaco, 'Lucida Console', 'Liberation Mono', 'DejaVu Sans Mono', 'Bitstream Vera Sans Mono', 'Courier New', monospace, serif; margin: 0px; padding: 0px; vertical-align: baseline; white-space: inherit;"><span style="white-space: inherit;">2014-12-31 </span>11:48:18.825 [main] INFO org.hibernate.cfg.Environment - HHH000206: hibernate.properties not found
<span style="white-space: inherit;">2014-12-31 </span>11:48:35.377 [qtp1484319352-19] ERROR c.w.b.c.ControllerErrorHandler -
org.springframework.beans.TypeMismatchException: Failed to convert value of type 'java.lang.String' to required type 'org.joda.time.LocalDate'; nested exception is org.springframework.core.convert.ConversionFailedException: Failed to convert from type java.lang.String to type @org.springframework.web.bind.annotation.RequestParam @org.springframework.format.annotation.DateTimeFormat org.joda.time.LocalDate for value '[2013-03-26]'; nested exception is java.lang.IllegalArgumentException: Invalid format: " [2013-03-26]"
at org.springframework.beans.TypeConverterSupport.doConvert(TypeConverterSupport.java:68) ~[spring-beans-3.2.1.RELEASE.jar:3.2.1.RELEASE]
at org.springframework.beans.TypeConverterSupport.convertIfNecessary(TypeConverterSupport.java:45) ~[spring-beans-3.2.1.RELEASE.jar:3.2.1.RELEASE]
at org.springframework.validation.DataBinder.convertIfNecessary(DataBinder.java:595) ~[spring-context-3.2.1.RELEASE.jar:3.2.1.RELEASE]
at org.springframework.web.method.annotation.AbstractNamedValueMethodArgumentResolver.resolveArgument(AbstractNamedValueMethodArgumentResolver.java:98) ~[spring-web-3.2.1.RELEASE.jar:3.2.1.RELEASE]
at org.springframework.web.method.support.HandlerMethodArgumentResolverComposite.resolveArgument(HandlerMethodArgumentResolverComposite.java:77) ~[spring-web-3.2.1.RELEASE.jar:3.2.1.RELEASE]
at org.springframework.web.method.support.InvocableHandlerMethod.getMethodArgumentValues(InvocableHandlerMethod.java:162) ~[spring-web-3.2.1.RELEASE]
<span style="white-space: inherit;">2014-12-31 </span>11:48:55.784 [main] INFO o.h.tool.hbm2ddl.SchemaUpdate - HHH000396: Updating schema</code></pre></div><h2>Solution</h2><pre style="font-family: Courier New, Courier, monospace;">sort -nmbs -k1.1,1.4 -k1.6,1.7 -k1.9,1.10 -k2.1,2.2 -k2.4,2.5 -k2.7,2.8 -k2.10,2.12 file1.log file2.log > merged.log</pre><pre style="font-family: Courier New, Courier, monospace;"></pre>The above command does the trick. Of course, input may be provided with wildcards as well. Like <span style="font-family: Courier New, Courier, monospace;">file?.log</span> or <span style="font-family: Courier New, Courier, monospace;">*.log</span> instead specifying each file separately.<br />
<h2>Explanation</h2>According to the man pages used switches mean:<br />
<blockquote class="tr_bq" style="font-size:90%"><span style="font-family: Courier New, Courier, monospace;">-n, --numeric-sort - compare according to string numerical value.</span><br />
<span style="font-family: Courier New, Courier, monospace;">-b, --ignore-leading-blanks - ignore leading blanks.</span><br />
<span style="font-family: Courier New, Courier, monospace;">-s, --stable - stabilize sort by disabling last-resort comparison</span><br />
<span style="font-family: Courier New, Courier, monospace;">-m, --merge - merge already sorted files; do not sort</span><br />
<span style="font-family: Courier New, Courier, monospace;">-k, --key=POS1[,POS2] - start a key at POS1 (origin 1), end it at POS2 (default end of line)</span></blockquote>It's not easy to get comprehensive info about <i>sort</i> command. However while experimenting with the command I got some insight and I'll try to give a some explanation. If you find any inaccuracies or mistakes please leave a comment.<br />
<h3>Compare only numeric values</h3><div>The <span style="font-family: Courier New, Courier, monospace;">-n</span> switch is supposed to speed up numeric comparison. We want that.</div><div><br />
</div><div>Apart from this however, apparently it stops comparing key whenever there is a non-numeric character in it. That's crucial for keeping multi-lines entries like stacktraces in place (see below).</div><h3>Merge, don't sort</h3>Log files are already ordered so we don't want to sort them again, only determine which line goes first upon merging. That's why <span style="font-family: Courier New, Courier, monospace;">-m</span> switch is used.<br />
<div><br />
<div>When merge switch is combined with numeric sort, lines which doesn't have numeric values for specified keys 'are preferred' in comparison over lines with proper keys (those containing date/time). This way stacktrace lines are copied to output file until next line with date/time key is spotted.</div><div><br />
I think that's a bit accidental behaviour but really crucial for our case.</div><h3>Specify proper keys</h3><div>The most important part are keys for sort (merge) comparison. A key is specified with <span style="font-family: Courier New, Courier, monospace;">-k</span> switch followed by a column position in a file line. Let say <span style="font-family: Courier New, Courier, monospace;">-k1,5</span> means that sort (merge) comparison is done by all columns from column 1 to column 5. By default columns are delimited by blanks, like spaces or tabs.</div><div>Specifying only a single column like <span style="font-family: Courier New, Courier, monospace;">-k2</span> results with comparison done by the column and <u>everything behind it till the end of a line</u>. That's why it's important to specify at least two columns or the same column twice, like <span style="font-family: Courier New, Courier, monospace;">-k1,1</span> if there is only one column we want to order by.</div><div><br />
</div><div>As we are concern in preserving date-time log entries order, it seems that in our case sufficient should be a key like <span style="font-family: Courier New, Courier, monospace;">-k1,2</span>. First column is date, second column is time, voila!. There is a catch though. As mentioned above, key comparison with <span style="font-family: Courier New, Courier, monospace;">-n</span> switch used will stop on any non-numeric character, which is dash after year in the sample log entries. This means that only a year going to be compared as a sort key upon merging and we'd end up with a the same result as if <span style="font-family: Courier New, Courier, monospace;">cat *.log > merged.log</span> command was used -considering all log entries in input files are from the same year. Which is usually the case, obviously.</div><div>On the other hand not using <span style="font-family: Courier New, Courier, monospace;">-n</span> switch sorts input files which will result with all the stactrace lines (for all the stacktraces) clustered in alphabetical order at the top of the file. Not good...</div><div>That's why keys needs to be specified in more granular way by pointing to specific character positions in each column. It can be done with a dot and in-a-column-position of a character like <span style="font-family: Courier New, Courier, monospace;">-k1.1,1.4</span> for four digits of a year, then <span style="font-family: Courier New, Courier, monospace;">-k1.6,1.7</span> for first and second digit of a month, <span style="font-family: 'Courier New', Courier, monospace;">-k1.9,1.10</span> for day digits, <span style="font-family: 'Courier New', Courier, monospace;">-k2.1,2.2</span> for hour digits, and so on.</div><div><br />
</div><div>Keys themselves may be provided in a different order for the command if your logs format is different (all input files need to share the same format though). Let say each entry starts with a date but written as 12/31/2014. Just go with following key switches then:</div><div><span style="font-family: 'Courier New', Courier, monospace;">-k1.7,1.10 </span><span style="font-family: Courier New, Courier, monospace;">-k1.1,1.2 </span><span style="font-family: Courier New, Courier, monospace;">-k1.4,1.5</span> (year, month, day).</div><h3>Ignore leading blanks</h3><div>This probably doesn't changes anything for our particular case but I left <span style="font-family: Courier New, Courier, monospace;">-b</span> just in case as the most of stactrace lines begin with spaces.</div><h3>Stabilize sort</h3></div><div>The <span style="font-family: Courier New, Courier, monospace;">-s</span> switch disables <i>last-resort comparison</i>. That's the default behaviour which, whenever keys by which two lines are being compared are the same, falls back to full string comparison of the whole lines.<br />
We like to preserve original order of log entries even for lines logged in the exact same millisecond. That's why this switch may be helpful for our case. Moreover it may slightly speed up the command as well.</div>Unknownnoreply@blogger.com1tag:blogger.com,1999:blog-600731584864808194.post-11366893818509991722013-06-29T02:03:00.005+02:002013-06-29T23:48:33.684+02:00Grails enum custom database value mapping<h3>About</h3>How to map a custom value and type of <span style="font-family: "Courier New",Courier,monospace;">enum</span> constants into database with Grails Domain.<br />
<h4>TL;DR</h4>Just add <i>id</i> field to the <span style="font-family: "Courier New",Courier,monospace;">enum</span> class and set its value for each <span style="font-family: "Courier New",Courier,monospace;">enum</span> constant.<br />
<h3>Example case</h3>When modelling domain there is often some <span style="font-family: "Courier New",Courier,monospace;">enum</span> domain class introduced. Such as <i>WhateverType</i> or <i>SomethingsStatus</i>. Let say we want to use ordinal instead of default GORM's text mapping.<br />
<pre class="default prettyprint prettyprinted brush:groovy">class SomeDomainElement {
Level level
static mapping = {
level enumType: 'ordinal'
}
}</pre>Our enum presents itself as follows:<br />
<pre class="default prettyprint prettyprinted brush:groovy">enum Level {
EASY,
MEDIUM,
HARD
}</pre>Latter introduction of a new level may happen. Lest say ADVANCED. It would be really tempting to place such between levels MEDIUM and HARD. This however would have changed the position number of level HARD. Stop! Database mapping will change either. What about already stored 'levels HARD'?<br />
<h3>Solution</h3>Remove the mapping block from <span style="font-family: "Courier New",Courier,monospace;">SomeDomainElement</span>. It won't be needed any more. Just add the <i><span style="font-family: inherit;">id</span></i> field to the <span style="font-family: "Courier New",Courier,monospace;">enum</span> constants.<br />
<pre class="default prettyprint prettyprinted brush:groovy">enum Level {
EASY(1),
MEDIUM(2),
ADVANCED(4),
HARD(3)
final int id
private Level(int id) { this.id = id }
}</pre>The field must be named <i>id</i> so Grails would map it automatically as DB value.<br />
<br />
Any <i>serializable</i> and known by Hibernate type can be used instead of <span style="font-family: "Courier New",Courier,monospace;">int</span>. Like <span style="font-family: "Courier New",Courier,monospace;">char</span>, <span style="font-family: "Courier New",Courier,monospace;">String</span>, <span style="font-family: "Courier New",Courier,monospace;">BigDecimal</span>, <span style="font-family: "Courier New",Courier,monospace;">Date</span> and so on.Unknownnoreply@blogger.com4tag:blogger.com,1999:blog-600731584864808194.post-47193536195042814962013-04-06T03:17:00.000+02:002013-04-06T12:01:20.063+02:00Thought static method can't be easy to mock, stub nor track? Wrong!No matter why, no matter is it a good idea. Sometimes one just wants to check or it's necessary to be done. Mock a static method, woot? Impossibru!<br />
<br />
In pure Java world it is still a struggle. But <a href="http://groovy.codehaus.org/" target="_blank">Groovy</a> allows you to do that really simple. Well, not groovy alone, but with a great support of <a href="http://docs.spockframework.org/en/latest/#" target="_blank">Spock</a>.<br />
<br />
Lets move on straight to the example. To catch some context we have an abstract for the example needs. A marketing project with a set of offers. One to many.<br />
<br />
<pre class="brush:groovy">import spock.lang.Specification
class OfferFacadeSpec extends Specification {
OfferFacade facade = new OfferFacade()
def setup() {
GroovyMock(Project, global: true)
}
def 'delegates an add offer call to the domain with proper params'() {
given:
Map params = [projId: projectId, name: offerName]
when:
Offer returnedOffer = facade.add(params)
then:
1 * Project.addOffer(projectId, _) >> { projId, offer -> offer }
returnedOffer.name == params.name
where:
projectId | offerName
1 | 'an Offer'
15 | 'whasup!?'
123 | 'doskonała oferta - kup teraz!'
}
}</pre>
So we test a <span style="font-family: "Courier New",Courier,monospace;">facade</span> responsible for handling <i>"add offer to the project</i>" call triggered somewhere in a GUI.<br />
We want to ensure that static method<span style="font-family: "Courier New",Courier,monospace;"> Project.addOffer(long, Offer)</span> will receive correct params when <span style="font-family: "Courier New",Courier,monospace;">java.util.Map</span> with user form input comes to the <span style="font-family: "Courier New",Courier,monospace;">facade.add(params)</span>.<br />
This is unit test, so how <span style="font-family: "Courier New",Courier,monospace;">Project.addOffer()</span> works is out of scope. Thus we want to <b>stub it</b>.<br />
<br />
The most important is a <span style="font-family: "Courier New",Courier,monospace;">GroovyMock(Project, global: true) </span>statement.<br />
What it does is modifing <span style="font-family: "Courier New",Courier,monospace;">Project</span> class to behave like a Spock's mock.<span style="font-family: "Courier New",Courier,monospace;"> </span><br />
<span style="font-family: "Courier New",Courier,monospace;">GroovyMock()</span> itself is a method inherited from <span style="font-family: "Courier New",Courier,monospace;">Specification</span><i>. </i>The <span style="font-family: "Courier New",Courier,monospace;">global</span> flag is necessary to enable mocking static methods<i>.</i><br />
However when one comes to the need of mocking static method, author of Spock Framework advice to consider redesigning of implementation. It's not a bad advice, I must say.<br />
<br />
Another important thing are assertions at <span style="font-family: "Courier New",Courier,monospace;">then:</span> block. First one checks an interaction, if the <span style="font-family: "Courier New",Courier,monospace;">Project.addOffer()</span> method was called exactly once, with a 1st argument equal to the <span style="font-family: "Courier New",Courier,monospace;">projectId</span> and some other param (we don't have an object instance yet to assert anything about it).<br />
Right shit operator leads us to the stub which replaces original method implementation by such statement.<br />
As a good stub it does nothing. The original method definition has return type <span style="font-family: "Courier New",Courier,monospace;">Offer</span>. The stub needs to do the same. So an <span style="font-family: "Courier New",Courier,monospace;">offer</span> passed as the 2nd argument is just returned.<br />
Thanks to this we can assert about <span style="font-family: "Courier New",Courier,monospace;">name</span> property if it's equal with the value from <span style="font-family: "Courier New",Courier,monospace;">params</span>. If no return was designed the <span style="font-family: "Courier New",Courier,monospace;">name</span> could be checked inside the stub <a href="http://groovy.codehaus.org/Closures" target="_blank"><span style="font-family: "Courier New",Courier,monospace;">Closure</span></a>, prefixed with an <span style="font-family: "Courier New",Courier,monospace;">assert</span> keyword.<br />
<br />
Worth of mentioning is that if you want to track interactions of original static method implementation without replacing it, then you should try using <span style="font-family: "Courier New",Courier,monospace;">GroovySpy</span> instead of <span style="font-family: "Courier New",Courier,monospace;">GroovyMock</span>.<br />
<br />
Unfortunately static methods declared at Java object can't be treated in such ways. Though regular mocks and whole goodness of Spock can be used to test pure Java code, which is awesome anyway :)Unknownnoreply@blogger.com1tag:blogger.com,1999:blog-600731584864808194.post-91425371046901723242013-02-21T23:16:00.002+01:002014-04-12T18:22:45.920+02:00Grails session timeout without XMLThis article shows clean, non hacky way of configuring featureful event listeners for Grails application servlet context. Feat. HttpSessionListener as a Spring bean example with session timeout depending on whether user account is premium or not.<br />
<h2>Common approaches</h2>Speaking of session timeout config in Grails, a default approach is to install templates with a command. This way we got direct access to <span style="font-family: Courier New, Courier, monospace;">web.xml</span> file. Also more unnecessary files are created. Despite that <u>unnecessary files are unnecessary</u>, we should also remember some other common knowledge: <b>XML is not for humans</b>.<br />
<br />
Another, a bit more hacky, way is to create mysterious <span style="font-family: Courier New, Courier, monospace;">scripts/_Events.groovy</span> file. Inside of which, by using not less enigmatic closure: <span style="font-family: 'Courier New', Courier, monospace;">eventWebXmlEnd = { filename -> ... }</span><span style="font-family: inherit;">, </span>we can parse and hack into <span style="font-family: Courier New, Courier, monospace;">web.xml</span><span style="font-family: inherit;"> with a help of </span><span style="font-family: Courier New, Courier, monospace;">XmlSlurper</span>.<br />
Even though lot of Grails plugins do it similar way, still it’s not really straightforward, is it? Besides, where’s the IDE support? Hello!?<br />
<br />
Examples of both above ways can be seen on <a href="http://stackoverflow.com/questions/11262450/change-session-timeout-for-netbeans-embedded-grails" target="_blank">StackOverflow</a>.<br />
<h2>Simpler and cleaner way</h2>By adding just a single line to the already generated <span style="font-family: Courier New, Courier, monospace;">init</span> closure we have it done:<br />
<pre class="brush:groovy">class BootStrap {
def init = { servletContext ->
servletContext.addListener(OurListenerClass)
}
}</pre><br />
Allrighty, this is enough to avoid XML. Sweets are served after the main course though :)<br />
<h2>Listener as a Spring bean</h2>Let us assume we have a requirement. Set a longer session timeout for premium user account.<br />
Users are authenticated upon session creation through SSO.<br />
<br />
To easy meet the requirements just instantiate the <span style="font-family: Courier New, Courier, monospace;">CustomTimeoutSessionListener</span> as Spring bean at resources.groovy. We also going to need some source of the user custom session timeout. Let say a <span style="font-family: Courier New, Courier, monospace;">ConfigService</span>.<br />
<pre class="brush:groovy">beans = {
customTimeoutSessionListener(CustomTimeoutSessionListener) {
configService = ref('configService')
}
}</pre><br />
With such approach BootStrap.groovy has to by slightly modified. To keep control on listener instantation, instead of passing listener class type, Spring bean is injected by Grails and the instance passed:<br />
<pre class="brush:groovy">class BootStrap {
def customTimeoutSessionListener
def init = { servletContext ->
servletContext.addListener(customTimeoutSessionListener)
}
}</pre><br />
An example <span style="font-family: Courier New, Courier, monospace;">CustomTimeoutSessionListener</span> implementation can look like:<br />
<pre class="brush:groovy">import javax.servlet.http.HttpSessionEvent
import javax.servlet.http.HttpSessionListener
import your.app.ConfigService
class CustomTimeoutSessionListener implements HttpSessionListener {
ConfigService configService
@Override
void sessionCreated(HttpSessionEvent httpSessionEvent) {
httpSessionEvent.session.maxInactiveInterval = configService.sessionTimeoutSeconds
}
@Override
void sessionDestroyed(HttpSessionEvent httpSessionEvent) { /* nothing to implement */ }
}</pre>Having at hand all power of the Spring IoC this is surely a good place to load some persisted user’s account stuff into the session or to notify any other adequate bean about user presence.<br />
<h2>Wait, what about the user context?</h2>Honest answer is: that depends on your case. Yet here’s an example of <span style="font-family: Courier New, Courier, monospace;">getSessionTimeoutMinutes() </span>implementation using Spring Security:<br />
<pre class="brush:groovy">import org.springframework.security.core.context.SecurityContextHolder
class ConfigService {
static final int 3H = 3 * 60 * 60
static final int QUARTER = 15 * 60
int getSessionTimeoutSeconds() {
String username = SecurityContextHolder.context?.authentication?.principal
def account = Account.findByUsername(username)
return account?.premium ? 3H : QUARTER
}
}</pre>This example is simplified. Does not contain much of <i>defensive programming</i>. Just an assumption that principal is already set and is a String - unique username. Thanks to Grails convention our <span style="font-family: Courier New, Courier, monospace;">ConfigService</span> is transactional so the Account domain class can use GORM dynamic finder.<br />
OK, config fetching implementation details are out of scope here anyway. You can get, load, fetch, obtain from wherever you like to. Domain persistence, principal object, role config, external file and so on...<br />
<h2>Any gotchas?</h2>There is one. When running <span style="font-family: Courier New, Courier, monospace;">grails test</span> command, <span style="font-family: Courier New, Courier, monospace;">servletContext</span> comes as some mocked class instance without <span style="font-family: Courier New, Courier, monospace;">addListener</span> method. Thus we going to have a <span style="font-family: Courier New, Courier, monospace;">MissingMethodException</span> when running tests :(<br />
<br />
Solution is typical:<br />
<pre class="brush:groovy">def init = { servletContext ->
if (Environment.current != Environment.TEST) {
servletContext.addListener(customTimeoutSessionListener)
}
}</pre>An unnecessary obstacle if you ask me. Should I submit a Jira issue about that?<br />
<h2>TL;DR</h2>Just implement a <span style="font-family: Courier New, Courier, monospace;">HttpSessionListener</span>. Create a <i>Spring</i> bean of the listener. Inject it into BootStrap.groovy and call <span style="font-family: Courier New, Courier, monospace;">servletContext.addListener(injectedListener)</span>.Unknownnoreply@blogger.com12tag:blogger.com,1999:blog-600731584864808194.post-35495298923745835932012-11-26T23:04:00.000+01:002013-02-22T00:40:42.305+01:00Multi module Gradle project with IDE supportThis article is a short how-to about multi-module project setup with usage of the Gradle automation build tool.<br />
<br />
Here's how Rich Seller, a StackOverflow user, <a href="http://stackoverflow.com/questions/1163173/why-use-gradle-instead-of-ant-or-maven" target="_blank">describes</a> Gradle:<br />
<blockquote class="tr_bq">
<span style="font-family: Times,"Times New Roman",serif;"><span style="color: #444444;"><span style="font-family: Georgia,"Times New Roman",serif;">Gradle promises to hit the sweet spot between Ant and Maven. It uses Ivy's
approach for dependency resolution. It allows for convention over
configuration but also includes Ant tasks as first class citizens. It
also wisely allows you to use existing Maven/Ivy repositories</span></span>.</span></blockquote>
So why would one use yet another JVM build tool such as Gradle? The answer is simple: to avoid frustration involved by Ant or Maven.<br />
<h2>
Short story</h2>
I was fooling around with some fresh proof of concept and needed a build tool. I'm pretty familiar with Maven so created project from an artifact, and opened the build file, pom.xml for further tuning.<br />
I had been using Grails with its own build system (similar to Gradle, btw) already for some time up then, so after quite a time without Maven, I looked on the pom.xml and found it to be really repulsive.<br />
<br />
Once again I felt clearly: <u>XML is not for humans</u>.<br />
<br />
After quick googling I found Gradle. It was still in beta (0.8 version) back then, but it's configured with Groovy DSL and that's what a human likes :)<br />
<h2>
Where are we</h2>
In the time Ant can be met but among IT guerrillas, Maven is still on top and couple of others like for example Ivy conquer for the best position, Gradle smoothly went into its mature age. It's now available in 1.3 version, released at 20th of November 2012. I'm glad to recommend it to anyone looking for relief from XML configured tools, or for anyone just looking for simple, elastic and powerful build tool.<br />
<h2>
Lets build</h2>
I have already written <a href="http://blog.tamashumi.com/2012/09/how-to-automate-tests-with-groovy-20.html" target="_blank">about basic project structure</a> so I skip this one, reminding only the basic project structure:<br />
<pre style="line-height: 1.1;"><project root>
│
├── build.gradle
└── src
├── main
│ ├── java
│ └── groovy
│
└── test
├── java
└── groovy</pre>
Have I just referred myself for the 1st time? Achievement unlocked! ;)<br />
<br />
Gradle as most build tools is run from a command line with parameters. The main parameter for Gradle is a 'task name', for example we can run a command: <span style="font-family: "Courier New",Courier,monospace;">gradle build</span>.<br />
There is no 'create project' task, so the directory structure has to be created by hand. This isn't a hassle though.<br />
Java and groovy sub-folders aren't always mandatory. They depend on what compile plugin is used.<br />
<h4>
Parent project</h4>
Consider an example project 'the-app' of three modules, let say:<br />
<ol>
<li>database communication layer</li>
<li>domain model and services layer</li>
<li>web presentation layer</li>
</ol>
Our project directory tree will look like:<br />
<pre style="line-height: 1.1;">the-app
│
├── dao-layer
│ └── src
│
├── domain-model
│ └── src
│
├── web-frontend
│ └── src
│
├── build.gradle
└── settings.gradle</pre>
<i>the-app</i> itself has no <i>src</i> sub-folder as its purpose is only to contain sub-projects and build configuration. If needed it could've been provided with own <i>src</i> though.<br />
<br />
To glue modules we need to fill <i>settings.gradle</i> file under <i>the-app</i> directory with a single line of content specifying module names:<br />
<pre class="brush:groovy">include 'dao-layer', 'domain-model', 'web-frontend'</pre>
Now the <span style="font-family: "Courier New",Courier,monospace;">gradle projects</span> command<span style="font-family: "Courier New",Courier,monospace;"></span> can be executed to obtain such a result:<br />
<pre style="line-height: 1.1;">:projects
------------------------------------------------------------
Root project
------------------------------------------------------------
Root project 'the-app'
+--- Project ':dao-layer'
+--- Project ':domain-model'
\--- Project ':web-frontend'
</pre>
...so we know that Gradle noticed the modules. However <span style="font-family: "Courier New",Courier,monospace;">gradle build</span> command won't run successful yet because <i>build.gradle</i> file is still empty.<br />
<h4>
Sub project</h4>
As in Maven we can create separate build config file per each module. Let say we starting from DAO layer.<br />
Thus we create a new file <i>the-app/dao-layer/build.gradle</i> with a line of basic build info (notice the new <i>build.gradle</i> was created under sub-project directory):<br />
<pre class="brush:groovy">apply plugin: 'java'</pre>
This single line of config for any of modules is enough to execute <span style="font-family: "Courier New",Courier,monospace;">gradle build</span> command under <i>the-app</i> directory with following result:<br />
<pre style="line-height: 1.1;">:dao-layer:compileJava
:dao-layer:processResources UP-TO-DATE
:dao-layer:classes
:dao-layer:jar
:dao-layer:assemble
:dao-layer:compileTestJava UP-TO-DATE
:dao-layer:processTestResources UP-TO-DATE
:dao-layer:testClasses UP-TO-DATE
:dao-layer:test
:dao-layer:check
:dao-layer:build
BUILD SUCCESSFUL
Total time: 3.256 secs</pre>
To use Groovy plugin slightly more configuration is needed:<br />
<pre class="brush:groovy">apply plugin: 'groovy'
repositories {
mavenLocal()
mavenCentral()
}
dependencies {
groovy 'org.codehaus.groovy:groovy-all:2.0.5'
}
</pre>
At lines 3 to 6 Maven repositories are set. At line 9 dependency with groovy library version is specified. Of course plugin as 'java', 'groovy' and many more can be mixed each other.<br />
<br />
If we have <i>settings.gradle</i> file and a <i>build.gradle</i> file for each module, there is no need for parent <i>the-app/build.gradle</i> file at all. Sure that's true but we can go another, better way.<br />
<h4>
One file to rule them all </h4>
Instead of creating many <i>build.gradle</i> config files, one per each module, we can use only the parent's one and make it a bit more juicy. So let us move the <i>the-app/dao-layer/build.gradle</i> a level up to <i>the-app/build-gradle</i> and fill it with new statements to achieve full project configuration:<br />
<pre class="brush:groovy">def langLevel = 1.7
allprojects {
apply plugin: 'idea'
group = 'com.tamashumi'
version = '0.1'
}
subprojects {
apply plugin: 'groovy'
sourceCompatibility = langLevel
targetCompatibility = langLevel
repositories {
mavenLocal()
mavenCentral()
}
dependencies {
groovy 'org.codehaus.groovy:groovy-all:2.0.5'
testCompile 'org.spockframework:spock-core:0.7-groovy-2.0'
}
}
project(':dao-layer') {
dependencies {
compile 'org.hibernate:hibernate-core:4.1.7.Final'
}
}
project(':domain-model') {
dependencies {
compile project(':dao-layer')
}
}
project(':web-frontend') {
apply plugin: 'war'
dependencies {
compile project(':domain-model')
compile 'org.springframework:spring-webmvc:3.1.2.RELEASE'
}
}
idea {
project {
jdkName = langLevel
languageLevel = langLevel
}
}</pre>
At the beginning simple variable <i>langLevel</i> is declared. It's worth knowing that we can use almost any Groovy code inside build.gradle file, statements like for example <i>if</i> conditions, <i>for</i>/<i>while</i> loops, <i>closures</i>, <i>switch-case</i>, etc... Quite an advantage over inflexible XML, isn't it?<br />
<br />
Next the <i>allProjects</i> block. Any configuration placed in it will influence - what a surprise - all projects, so the parent itself and sub-projects (modules). Inside of the block we have the IDE (Intellij Idea) plugin applied which I wrote more about in <a href="http://blog.tamashumi.com/2012/09/how-to-automate-tests-with-groovy-20.html" target="_blank">previous article</a> (look under "IDE Integration" heading). Enough to say that with this plugin applied here, command <span style="font-family: "Courier New",Courier,monospace;">gradle idea</span> will generate Idea's project files with modules structure and dependencies. This works really well and plugins for other IDEs are available too.<br />
Remaining two lines at this block define <i>group</i> and <i>version</i> for the project, similar as this is done by Maven.<br />
<br />
After that <i>subProjects</i> block appears. It's related to all modules but not the parent project. So here the Groovy language plugin is applied, as all modules are assumed to be written in Groovy.<br />
Below <i>source</i> and <i>target</i> language level are set.<br />
After that come references to standard Maven <i>repositories</i>.<br />
At the end of the block <i>dependencies</i> to groovy version and test library - Spock framework.<br />
<br />
Following blocks, <i>project(':module-name')</i>, are responsible for each module configuration. They may be omitted unless <i>allProjects</i> or <i>subProjects</i> configure what's necessary for a specific module. In the example per module configuration goes as follow:<br />
<ul>
<li><i>Dao-layer</i> module has dependency to an ORM library - Hibernate</li>
<li><i>Domain-model</i> module relies on <i>dao-layer</i> as a dependency. Keyword <i>project</i> is used here again for a reference to other module.</li>
<li><i>Web-frontend</i> applies 'war' plugin which build this module into java web archive. Besides it referes to <i>domain-model</i> module and also use Spring MVC framework dependency.</li>
</ul>
<br />
At the end in <i>idea</i> block is basic info for IDE plugin. Those are parameters corresponding to the Idea's project general settings visible on the following screen shot.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjD_cY-fkgEALJ5OT15OnbknDLh2Lpiu8__ETB0-bowNvRLsS_5tu9KOsD_0_OrUs3PjTdpG0YHGuBGqETYWKMWN820d4snDH6laeL0Q_EgC1uSBCIWT26Sft1CXsSOoVMTISv2x-C5FTA/s1600/idea-project-general-settings.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="185" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjD_cY-fkgEALJ5OT15OnbknDLh2Lpiu8__ETB0-bowNvRLsS_5tu9KOsD_0_OrUs3PjTdpG0YHGuBGqETYWKMWN820d4snDH6laeL0Q_EgC1uSBCIWT26Sft1CXsSOoVMTISv2x-C5FTA/s320/idea-project-general-settings.png" width="320" /></a></div>
<br />
<i>jdkName</i> should match the IDE's SDK name otherwise it has to be set manually under IDE on each Idea's project files (re)generation with <span style="font-family: "Courier New",Courier,monospace;">gradle idea</span> command.<br />
<h2>
Is that it? </h2>
In the matter of simplicity - yes. That's enough to automate modular application build with custom configuration per module. Not a rocket science, huh? Think about Maven's XML. It would take more effort to setup the same and still achieve less expressible configuration quite far from user-friendly.<br />
<br />
Check the online <a href="http://www.gradle.org/docs/current/userguide/userguide.html" target="_blank">user guide</a> for a lot of configuration possibilities or better download Gradle and see the sample projects.<br />
As a tasty bait take a look for this short choice of available plugins:<br />
<ul>
<li>java</li>
<li>groovy </li>
<li>scala</li>
<li>cpp</li>
<li>eclipse</li>
<li>netbeans</li>
<li>ida </li>
<li>maven</li>
<li>osgi</li>
<li>war</li>
<li>ear</li>
<li>sonar</li>
<li>project-report</li>
<li>signing </li>
</ul>
<a href="http://wiki.gradle.org/display/GRADLE/Plugins" target="_blank">and more, 3rd party plugins...</a>Unknownnoreply@blogger.com3tag:blogger.com,1999:blog-600731584864808194.post-8300165036013883932012-09-15T18:59:00.000+02:002015-04-15T00:14:58.558+02:00How to automate tests with Groovy 2.0, Spock and GradleThis is the launch of the 1st blog in my life, so cheers and have a nice reading!<br />
<h2>
y u no test?</h2>
<img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhP1Cko_NP7q2nszqWCt9EFBUXA_uPID0xPOgWfHio41iHW5Kfm7EDVuBZS48VEC0oJKKL5aiWIzeVYOCC1zeb7kG2FPXn6cOtOwU4UvqXeXNpcfbksZIq_-YDu2B-KVQ6QY9kTYaDifSI/s1600/y-u-no-guy.jpg" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;" />Couple of years ago I wasn't a big fan of unit testing. It was obvious to me that well prepared unit tests are crucial though. I didn't known why exactly crucial yet then. I just felt they are important. My disliking to write automation tests was mostly related to the effort necessary to prepare them. Also a <i>spaghetti code</i> was easily spotted in test sources.<br />
<h2>
Some goodies at hand</h2>
Now I know! Test are crucial to get a better design and a confidence. Confidence to improve without a hesitation. Moreover, now I have the tool to make test automation <i>easy as Sunday morning</i>... I'm talking about the <i><a href="http://code.google.com/p/spock/">Spock Framework</a></i>. If you got here probably already know what the Spock is, so I won't introduce it. Enough to say that Spock is an awesome unit testing tool which, thanks to Groovy AST Transformation, simplifies creation of tests greatly.<br />
<h2>
An obstacle</h2>
The point is, since a new major version of Groovy has been released (2.0), there is no matching version of Spock available yet.<br />
<h2>
What now?</h2>
Well, in a matter of fact there is such a version. It's still under development though. It can be obtained from <a href="http://oss.sonatype.org/content/repositories/snapshots/">this <i>Maven</i> repository</a>. We can of course use the <i>Maven</i> to build a project and run tests. But why not to go even more "groovy" way? XML is not for humans, is it? Lets use <i><a href="http://www.gradle.org/">Gradle</a></i>.<br />
<h2>
The build file</h2>
<u>Update:</u> at the end of the post is updated version of the build file.<br />
<pre class="brush:groovy">apply plugin: 'groovy'
apply plugin: 'idea'
def langLevel = 1.7
sourceCompatibility = langLevel
targetCompatibility = langLevel
group = 'com.tamashumi.example.testwithspock'
version = '0.1'
repositories {
mavenLocal()
mavenCentral()
maven { url 'http://oss.sonatype.org/content/repositories/snapshots/' }
}
dependencies {
groovy 'org.codehaus.groovy:groovy-all:2.0.1'
testCompile 'org.spockframework:spock-core:0.7-groovy-2.0-SNAPSHOT'
}
idea {
project {
jdkName = langLevel
languageLevel = langLevel
}
}</pre>
As you can see the <i>build.gradle</i> file is almost self-explanatory. Groovy plugin is applied to compile groovy code. It needs groovy-all.jar - declared in version 2.0 at dependencies block just next to Spock in version 0.7. What's most important, mentioned Maven repository URL is added at repositories block.<br />
<h2>
Project structure and execution</h2>
Gradle's default project directory structure is similar to Maven's one. Unfortunately there is no 'create project' task and you have to create it by hand. It's not a big obstacle though. The structure you will create will more or less look as follows: <br />
<pre style="line-height: 1.1;"><project root>
│
├── build.gradle
└── src
├── main
│ ├── groovy
└── test
└── groovy</pre>
To build a project now you can type command <span style="font-family: "Courier New",Courier,monospace;">gradle build</span> or <span style="font-family: "Courier New",Courier,monospace;">gradle test</span> to only run tests.<br />
<h2>
How about Java?</h2>
<b>You can test native Java code with Spock.</b> Just add <span style="font-family: "Courier New",Courier,monospace;">src/main/java</span> directory and a following line to the <i>build.gradle</i>: <br />
<pre class="brush:groovy">apply plugin: 'java'</pre>
This way if you don't want or just can't deploy Groovy compiled stuff into your production JVM for any reason, still whole goodness of testing with Spock and Groovy is at your hand.<br />
<h2>
A silly-simple example </h2>
Just to show that it works, here you go with a basic example.<br />
<h4>
Java simple example class:</h4>
<pre class="brush:java">public class SimpleJavaClass {
public int sumAll(int... args) {
int sum = 0;
for (int arg : args){
sum += arg;
}
return sum;
}
}</pre>
<h4>
Groovy simple example class:</h4>
<pre class="brush:groovy">class SimpleGroovyClass {
String concatenateAll(char separator, String... args) {
args.join(separator as String)
}
}</pre>
<h4>
The test, uhm... I mean the <i>Specification</i>:</h4>
<pre class="brush:groovy">class JustASpecification extends Specification {
@Unroll('Sums integers #integers into: #expectedResult')
def "Can sum different amount of integers"() {
given:
def instance = new SimpleJavaClass()
when:
def result = instance.sumAll(* integers)
then:
result == expectedResult
where:
expectedResult | integers
11 | [3, 3, 5]
8 | [3, 5]
254 | [2, 4, 8, 16, 32, 64, 128]
22 | [7, 5, 6, 2, 2]
}
@Unroll('Concatenates strings #strings with separator "#separator" into: #expectedResult')
def "Can concatenate different amount of integers with a specified separator"() {
given:
def instance = new SimpleGroovyClass()
when:
def result = instance.concatenateAll(separator, * strings)
then:
result == expectedResult
where:
expectedResult | separator | strings
'Whasup dude?' | ' ' as char | ['Whasup', 'dude?']
'2012/09/15' | '/' as char | ['2012', '09', '15']
'nice-to-meet-you' | '-' as char | ['nice', 'to', 'meet', 'you']
}
} </pre>
To run tests with <i>Gradle</i> simply execute command <span style="font-family: "Courier New",Courier,monospace;">gradle test</span>. Test reports can be found at <span style="font-family: "Courier New",Courier,monospace;"><project root>/build/reports/tests/index.html</span> and look kind a like this.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjPKEBOh-IO0yFblHMPh8KQY0CW_R1cwtpkL4m0H0VxF90-U8S2xnuE-K4LO0ZQx3wBIubiBcqb0J4FPC56twQY__fdJYiA_yDOsaDZKUf4fQ01THrNtZjXMsZvyE0pEAof_IfJIE8i_nE/s1600/Gradle+test+report.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjPKEBOh-IO0yFblHMPh8KQY0CW_R1cwtpkL4m0H0VxF90-U8S2xnuE-K4LO0ZQx3wBIubiBcqb0J4FPC56twQY__fdJYiA_yDOsaDZKUf4fQ01THrNtZjXMsZvyE0pEAof_IfJIE8i_nE/s400/Gradle+test+report.png" height="218" width="400" /></a></div>
<br />
Please note that, thanks to <span style="font-family: "Courier New",Courier,monospace;">@Unroll</span> annotation, test is executed once per each parameters row in the 'table' at specification's <span style="font-family: "Courier New",Courier,monospace;">where: block</span>. This isn't a Java label, but a AST transformation magic.<br />
<h2>
IDE integration</h2>
<h4>
Gradle's plugin for Iintellij Idea</h4>
I've added also Intellij Idea plugin for IDE project generation and some configuration for it (IDE's JDK name). To generate Idea's project files just run command: <span style="font-size: small;"><span style="font-family: "Courier New",Courier,monospace;">gradle idea</span></span> There are available Eclipse and Netbeans plugins too, however I haven't tested them. Idea's one works well.<br />
<h4>
Intellij Idea's plugins for Gradle</h4>
Idea itself has a light Gradle support built-in on its own. To not get confused: Gradle has plugin for Idea and Idea has plugin for Gradle. To get even more 'pluginated', there is also JetGradle plugin within Idea. However I haven't found good reason for it's existence - well, maybe excluding one. It shows dependency tree. There is a bug though - JetGradle work's fine only for lang level 1.6. Strangely all the plugins together do not conflict each other. They even give complementary, quite useful tool set.<br />
<h4>
Running tests under IDE</h4>
Jest to add something sweet this is how Specification looks when run with jUnit runner under Intellij Idea (right mouse button on JustASpecification class or whole folder of specification extending classes and select "Run ...". You'll see a nice view like this.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEin7QDSj-ANvmYWWECEAGOOVLG7a66FgsdPAg76DnqRRFCxSoMIliTuZjHOvd1WLFebZUu8tZNUv-gUZS726Zr9NGSs4lEn4XQMmTKdHuhh6hQLtBoRPPlYgMZ3YImDUYPs2jDxZCYbqYY/s1600/Spock+test+run+from+Idea+with+%2540Unroll.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEin7QDSj-ANvmYWWECEAGOOVLG7a66FgsdPAg76DnqRRFCxSoMIliTuZjHOvd1WLFebZUu8tZNUv-gUZS726Zr9NGSs4lEn4XQMmTKdHuhh6hQLtBoRPPlYgMZ3YImDUYPs2jDxZCYbqYY/s400/Spock+test+run+from+Idea+with+%2540Unroll.png" height="140" width="400" /></a></div>
<h2>
Building web application</h2>
If you need to build Java web application and bundle it as <i>war</i> archive just add plugin by typing the line <br />
<pre class="brush:groovy">apply plugin: 'war'</pre>
in the <i>build.gradle</i> file and create a directory <span style="font-family: "Courier New",Courier,monospace;">src/main/webapp</span>. <br />
<h2>
Want to know more?</h2>
If you haven't heard about Spock or Gradle before or just curious, check the following links: <br />
<ul>
<li><a href="http://code.google.com/p/spock/wiki/">Spock wiki</a> (most important info is under SpockBasics and Interactions)</li>
<li><a href="http://gradle.org/docs/current/userguide/userguide.html">Gradle user guide</a> </li>
</ul>
<h2>
What next?</h2>
The last thing left is to write the real production code you are about to test. No matter will it be Groovy or Java, I leave this to your need and invention. Of course, you are welcome to post a comments here. I'll answer or even write some more posts about the subject.<br />
<h2>
Important update</h2>
Spock version 0.7 has been released, so the above build file doesn't work anymore. It's easy to fix it though. Just remove last dash and a word SNAPSHOT from Spock dependency declaration. Other important thing is that now spock-core depends on groovy-all-2.0.5, so to avoid dependency conflict groovy dependency should be changed from version 2.0.1 to 2.0.5.<br />
Besides oss.sonata.org snapshots maven repository can be removed. No obstacles any more and the build file now looks as follows: <br />
<pre class="brush:groovy">apply plugin: 'groovy'
apply plugin: 'idea'
def langLevel = 1.7
sourceCompatibility = langLevel
targetCompatibility = langLevel
group = 'com.tamashumi.example.testwithspock'
version = '0.1'
repositories {
mavenLocal()
mavenCentral()
}
dependencies {
groovy 'org.codehaus.groovy:groovy-all:2.0.5'
testCompile 'org.spockframework:spock-core:0.7-groovy-2.0'
}
idea {
project {
jdkName = langLevel
languageLevel = langLevel
}
}</pre>
Unknownnoreply@blogger.com12