I would like to announce that new Android app has been released recently times by me. This time application is called PerlJobs. This application helps you as a Perl developer to find new job opportunities across the globe. Job offers are divided into sections : Standard, Mod, Catalyst, Mason, Telecommute and By Country. The main source of all jobs is website : https://jobs.perl.org
Yes! I finally managed to create it. Obviously it is not so pretty as it might be, but.. never mind :) If you would like to create your own Google Play Developer Page where you can add some promotion text and graphics (icon and background), just go to your Developer Console and then click Settings and then Developer Page. If you are looking for let's say 'inspiration', you can have a look on my Developer Page which link you can find below :
This time I would like to share with small snippet of code written in Java and Spring MVC which might allow you to pack and download some files (in this case .csv file) in ZIP archive. So, if you will hit URL http://localhost:8090/yourApp/download/zip, Zip archive will be downloaded with name 'download.zip'.
@ResponseBody @RequestMapping(value = {"/download/zip"}, method = RequestMethod.GET) public void downloadZipArchive(HttpServletResponse response) throws IOException { List<MyClass> list; //should contains some records! if (list != null && !list.isEmpty()) { if (list.size() > 200000) { response.setContentType("application/zip"); response.addHeader("Content-Disposition", "attachment; filename=\"download.zip\""); response.addHeader("Content-Transfer-Encoding", "binary"); OutputStream servletOutputStream = response.getOutputStream(); ZipOutputStream zos = new ZipOutputStream(servletOutputStream); int counter = 0; List<List<MyClass>> dividedlist = Lists.partition(list, 200000); for (List<MyClass> partition : dividedlist) { zos.putNextEntry(new ZipEntry("file_" + counter + ".csv")); CSVWriter writer = new CSVWriter(new OutputStreamWriter(zos)); writer.writeNext(new String[]{"HEADER"}); for (MyClass item : partition) { writer.writeNext(new String[]{item.getText()}); } writer.flush(); zos.closeEntry(); counter++; } zos.close(); response.getOutputStream().flush(); response.getOutputStream().close(); } } }
Guava FluentIterable - Get only first object or null from list
by GarciaPL on Tuesday, 23 February 2016
A few days ago I had issue, that I need to get first object from some list which meet my requirements. Of course I can create some loop, write some if statement. If I will find interesting me object, then I am gonna return it. If I will not find any useful in whole list, then I am will return null.
Above solution is done in quite old-style approach. Now it is time for functional programming! I found very useful a library called Guava and it's utility class called FluentIterable. It supports you to manipulate Iterable instances in a chained fashion. This class has a lot of functionalities, but I would like to focus only on one case - get first interesting object to my pattern or just return null.
MyClass interestingObjectOrNull = FluentIterable.from(myList) .firstMatch(new Predicate<MyClass>() { @Override public boolean apply(MyClass element) { return element.getId == 125L } }) .orNull();
And that's it! Simple, isn't ? All you need to remember to check returned object if it is null or not. Of course you might write as much complex apply pattern as you like.
Reference :
[1] Stackoverflow - Get only element of a collection view with Guava, without exception when there are multiple elements
[2] Pastebin - Source code
GPG error: http://downloads.hipchat.com Public key is not available
by GarciaPL on Saturday, 6 February 2016
Recently I had an issue during installation of HipChat from Atlassian on my Ubuntu. I mean that installation went well, but I had issue with GPG keys which was :
"GPG error: http://downloads.hipchat.com stable InRelease: The following signatures couldn't be verified because the public key is not available"
So, I managed to find that WebUpd8Team provides tool called y-ppa-manager. All you have to do is install y-ppa-manager like below :
sudo add-apt-repository ppa:webupd8team/y-ppa-manager sudo apt-get update sudo apt-get install y-ppa-manager
and then launch this tool. Select "Advanced" and then "Try to import all missing GPG keys". This operation might take a one or two minutes, so be calm and wait for notification. After that you can run sudo apt-get update to refresh repositories.
Reference : [1] Y PPA Manager - WebUpd8Team
In recent times I had issue with web application written in Spring. The problem was that some numbers stored in database as a BigDecimal's and Long's were not being stored/processed properly for different locales. On backend the numbers were processed of course using English locale, but when you have number saved with different locale the calculations might be different.
Saved BigDecimal's and Long's were processed against English locale, but presentation of numbers were based on appropriate locale of present user context.
Parse BigDecimal => 12,333,444
English => 12333444
Indonesian => 12333444
Print BigDecimal => 12345.50
English => 12345.50
Indonesian => 12345,50
Only difference for printed numbers for above locales was how decimal places is presented. For English we use dot. For Indonesian comma is used.
Parse Long => 12,333,444
English => 12333444
Indonesian => 12333444
Print Long => 12333444
English => 12333444
Indonesian => 12333444
For Long's the formatter we are going to just remove grouping commas.
So, below you can find CurrencyLocaleBigDecimalFormatter :
package pl.garciapl.test; import org.springframework.format.Formatter; import java.math.BigDecimal; import java.text.DecimalFormat; import java.text.NumberFormat; import java.text.ParseException; import java.util.Locale; public class CurrencyLocaleBigDecimalFormatter implements Formatter<BigDecimal> { @Override public BigDecimal parse(String text, Locale locale) throws ParseException { DecimalFormat format = (DecimalFormat) NumberFormat.getNumberInstance(Locale.ENGLISH); format.applyPattern("#,##0.00"); format.setParseBigDecimal(true); format.setGroupingUsed(true); return (BigDecimal) format.parse(text); } @Override public String print(BigDecimal object, Locale locale) { DecimalFormat format = (DecimalFormat) NumberFormat.getNumberInstance(locale); format.applyPattern("#,##0.00"); format.setParseBigDecimal(true); format.setGroupingUsed(false); return format.format(object); } }
and CurrencyLocaleLongFormatter :
package pl.garciapl.test; import org.springframework.format.Formatter; import java.text.DecimalFormat; import java.text.NumberFormat; import java.text.ParseException; import java.util.Locale; public class CurrencyLocaleLongFormatter implements Formatter<Long> { @Override public Long parse(String text, Locale locale) throws ParseException { DecimalFormat format = (DecimalFormat) NumberFormat.getNumberInstance(Locale.ENGLISH); format.applyPattern("#,##0.00"); format.setParseBigDecimal(false); format.setGroupingUsed(true); return (Long) format.parse(text); } @Override public String print(Long object, Locale locale) { DecimalFormat format = (DecimalFormat) NumberFormat.getNumberInstance(locale); format.applyPattern("#,##0.00"); format.setParseBigDecimal(false); format.setGroupingUsed(false); return format.format(object); } }
Also CurrencyLocaleFormatterRegistrar is needed because of Spring framework needs to register formatters in registry to use them.
package pl.garciapl.test; import org.springframework.format.Formatter; import org.springframework.format.FormatterRegistrar; import org.springframework.format.FormatterRegistry; import java.util.HashSet; import java.util.Set; public class CurrencyLocaleFormatterRegistrar implements FormatterRegistrar { private Set<Formatter> formatters = new HashSet<>(); public CurrencyLocaleFormatterRegistrar(Set<Formatter> formatters) { this.formatters = formatters; } @Override public void registerFormatters(FormatterRegistry registry) { for (Formatter element : this.formatters) { registry.addFormatter(element); } } }
And finally whole beans configuration for Spring
<bean id="currencyLocaleBigDecimalFormatter" class="ie.garciapl.test.CurrencyLocaleBigDecimalFormatter"/> <bean id="currencyLocaleLongFormatter" class="ie.garciapl.test.CurrencyLocaleLongFormatter"/> <bean id="currencyLocaleRegistrar" class="ie.garciapl.test.CurrencyLocaleFormatterRegistrar"> <constructor-arg> <set> <ref bean="currencyLocaleBigDecimalFormatter"/> <ref bean="currencyLocaleLongFormatter"/> </set> </constructor-arg> </bean>
Do not forget to plug into your conversionCurrencyService as below :
<mvc:annotation-driven conversion-service="conversionCurrencyService"/>
Reference : [1] Spring Docs - Formatters [2] Javabeat.net - Introduction to Spring Converters and Formatters [3] CurrencyLocaleBigDecimalFormatter [4] CurrencyLocaleLongFormatter [5] CurrencyLocaleFormatterRegistrar [6] CurrencyLocaleBigDecimalFormatterTest [7] CurrencyLocaleLongFormatterTest