Thursday, 27 August 2015

If there's an error, isn't it better to fail and show the error?


# if we didn't have a placeholder, we wouldn't have to escape the single quote
# but if we have a placeholder, then we have to escape the single quote
#   otherwise: single quote doesnt show AND placeholder doesnt receive our parameter!

mail.body.donate=Hi there, I'd like to donate ${0}


I was using Spring's MessageResource to load this value from a properties file, passing in a single item array with the value I wanted to show after the word "donate"

But for some reason, it kept showing only this:

Hi there, Id like to donate ${0}


I've had this problem for too days, and then eventually I removed this and replaced it with a message that only had letters and spaces, aside from the placeholder


Hi there I would like to donate ${0}


And it replaced it with:

Hi there I would like to donate $300


So it looked like it was either the "," or "'" (single quote) that was the problem.

Eventually, I found this page:


This part had the answer:

Java code:
1
2
3
4
5
private void printMessage(String code, Object... args) {
  Locale locale = new Locale("en");
  String message = messageSource.getMessage(code, args, locale);
  System.out.println(message);
}
1
2
3
printMessage("test.message1");
printMessage("test.message2""John");
printMessage("test.message3""message");
Output:
1
2
3
John's message
Johns message
Johns {0}
The first message does not take any arguments, so no MessageFormat is applied and the single quote does not need to be escaped. The second and third messages, however, are formatted by a MesssageFormat which processes the single quote characters. In these messages the single quotes should better be escaped with another single quote character otherwise they won't show up in the output.


I'm not a fan of this "fail, but partly work". I'd rather have complete failure with a clear indication of where things failed, rather than partially working, but no indication of why things are failing.


Thursday, 6 August 2015

When a deployment doesn't work, and logs don't show anything: Restart it! (AKA It was working on the other QA box!)

PROBLEM:

We have a number of QA (Quality Assurance, ie, testing) boxes. Release candidates (RC) go on a specific QA box, one that is more prod-like. The problem was an application that was working on the other QA boxes but not on the RC QA box.


We tailed the log files while testing the functionality - no errors.
 
We had a look at the libraries that were deployed. They were as expected.

We manually made calls to the service endpoints using curl - we were getting a 404! 

Okay, now what's going on?

Was it a mistake in the jar we released - in the past we've had some code not getting merged into master during release. Opened the jar - yup, contents were there.

Was it a mistake in the URL? Nope. It works on the other QA box.

Now doing a "ps" would usually show the libraries being loaded on the classpath, but this app was different and didn't actually do that. 

Could it be that the *old* version was still running? We had no quick way of knowing this. But the fact that the webapp didn't know this new endpoint even though we had the new jar file in the filesystem was pointing to this.

So we restarted the process. That fixed it! Functionality all working either through direct calls via curl or the webapp.


LESSON:

When investigating something that should already be working, the steps should be: 

1) Check the logs. 
2) Check that it's actually deployed 
3) If 1 or 2 don't show anything wrong, restart the application.  

Saves so much time.

The culprit was a Jenkins job that deployed the package but didn't successfully kill the old process. 


How do we check that the process is running the new code? Our plan is to have an endpoint that can be queried to show release information - so we know the libraries in use by the application currently running. Our Jenkins job should then check this URL after it's deployed the package, and send out an alert if it's not getting the expected results.

4) Have an endpoint showing the state of the running process, library versions and configuration
5) Get Jenkins to check the release info endpoint after it deploys a package



 

Friday, 31 July 2015

Reading in a file when directory names have spaces in them

PROBLEM:

We were running some errors in our Jenkins build of some code, even though the code works on our computers. 

java.io.FileNotFoundException: File '/var/lib/jenkins/workspace/Email%20Project%20Release/target/test-classes/com/company/mailFolder/sample_email.txt' does not exist

I ssh'd to the Jenkins box and tried to ls on the directory name:

and I got

ls: cannot access 
/var/lib/jenkins/workspace/Email%20Project%20Release/target/test-classes/com/company/mailFolder/sample_email.txt: No such file or directory

Then I realised it was the '%20' -- it was trying to load a url encoded directory name..

Doing an ls this directory worked:

ls -l "/var/lib/jenkins/workspace/Email Project Release/target/test-classes/com/company/mailFolder/sample_email.txt'

I looked in the code and it was doing this:

File mailFolder = new File(getClass().getResource("mailFolder"));
File mailFile = new File(mailFolder, "sample_email.txt");

I tested doing the first line with a folder that had spaces in it and I found it would return a path with any spaces replaced by '%20'


SOLUTION:

From stackoverflow, I found that the best way to get the correct folder reference was to do this

File mailFolder = FileUtils.toFile(getClass().getResource("mailFolder"));
File mailFile = new File(mailFolder, "sample_email.txt");

At first, I tried to load the file directly and it only returned null. Getting the File reference to the folder first, then creating the reference to the file is the only way that works, despite what the Stackoverflow article said (REF).



REF:


Monday, 23 February 2015

My favourite moment in "Halt and Catch Fire"


S01E09, at around 22:45

Gordon: "... You hit an overhang, and you can't climb up, and it's too steep to climb down. You realise what the word "jump" really means. And if I held your hand and counted to three.. I wasn't sure you'd come with me."

Donna: "We're married, Gordon. We already jumped."


That line just hit me. Hard.

Thursday, 30 October 2014

WTF Cnet? Put HREF attributes in those anchor tags! A link tag without a link is pretty stupid.


When is a an <a> anchor tag not really an anchor tag... when it doesn't have a href attribute. 

WTF Cnet. 


I was reading this article on Cnet and I started going through the list on the right of the page - "This Week's Must Reads" (see image)



Now normally, when I want to read articles, I open them in separate tabs so I can look at them after I finish the current tab. Now in this case the "Open In New Tab" option wasn't opening up in Chrome. So I call on "Inspect Element" option and I get this:

<a class="title" data-goto="5657a735-cbf6-40b4-8453-94cb94630900" data-url="/news/for-gorilla-glass-testers-life-is-a-daily-grind-and-scratch-and-drop/" data-s-object-id="TOC.2">

                            <div class="col-1">
                                <div class="progress">2</div>
                            </div>

                            <div class="col-3">
                                <div class="hed">For Gorilla Glass testers, life is a daily grind (and scratch and drop...)</div>

                                                                                                    <span class="topic">Phones</span>
                                                            </div>
                        </a>


The link probably only works after a click event. But what's the purpose of this? 

Now admittedly, I've been guilty of doing something similar last year, for SEO purposes. There were links on the website of my company that they wanted to de-prioritise as they wanted the main content links getting crawled first. So I did exactly the same technique - put the URL in a data attribute. I event reversed it, so that crawlers woudln't recognise the attribute as a URL and try to crawl it. But the links I did that on were only links to FAQ and generic help. People wouldn't normally go to them anyway. But this.. 

A list of most read articles on a news site is arguably on the same level of importance as the main article, as it leads people to consume more content on the site. So why would they make things a little more difficult for us tab-users by removing the href attribute?


Wednesday, 24 September 2014

PuTTY default colours suck, so replace it with a better colour scheme like zenburn

PuTTY defaults to horrible combinations like using black background, with blue text for directories. WTH, after all these years?

Replace that with a better colour scheme. I came across Zenburn for PuTTY.


Step 1:

Go to


Step 2:

Save this as a .reg file. Make sure you're saving the content, and not ending up with the HTML of the github page.

Step 3:

Right click, and then select "Merge"

You'll know if it worked as you'll get a message

In PuTTY, a "Zenburn" session will be created. This has your new, better colours.

Step 4: (do this for all your existing entries)

NOTE: this assumes that 
a. your session only has the hostname as its contents, because that's all you'll be copying.
b. your hostname is the same as your putty session name

Load the existing entry you want to change.
Copy the hostname to clipboard
Load the Zenburn session.
Paste the hostname into the session name
Paste the hostname into the host details
Click on Save

Test it by opening this session. Colours shoud be better now.

Repeat for all your PuTTY session entries.


Tuesday, 23 September 2014

Given a list of values, recursively go through subdirectories and find the matching files of a specific filename

Unix grep example:

fgrep -R -f sorted_untrusted_values_to_find.txt --include=".thisfile"

1. Given a list of values, contained in the file "sorted_unstrusted_values_to_find.txt", where each row has one value

-f sorted_untrusted_values_to_find.txt 

2. recursively traverse the subdirectories under our current location

 -R 

3. looking at the files named ".thisfile"

--include=".thisfile"

3. return the files that have a match



Wednesday, 30 July 2014

Moving your Git working directory from Linux to Windows? There are two issues that you're probably going to get

The simpler solution would be to just check out the repository, but in
some cases you probably have some branches and stashes in your local
repository that you don't want to lose. So if you want to keep your
current local repo, you'll definitely have to deal with these two
issues. Here's how to solve them.

A. The line endings issue. You want to make sure that you're not
inadvertently checking in CRLF line endings.

Make sure you set this:

git config --global core.autocrlf true

This tells Git to use the system's default line ending (CRLF) when
checking out and LF when checking in.

B. File permissions being changed by Cygwin

The executable bit on Git repository files will get changed, and you
will have permissions "changes" in your git respository immediately
after checkout. Fix this by turning git's core.filemode config to
false. Refer to this post:
https://groups.google.com/a/chromium.org/forum/?fromgroups=#!topic/chromium-dev/0EdNev3NNsw

1. Turn it for globally: git config --global core.filemode false
2. Turn it off for each repo: git config core.filemode false
3. Turn it off for all the submodules of each repo: git submodule
foreach --recursive git config core.filemode false

If you don't change do (B), then when you do 'git status' you'll find it listing a lot of files that have been changed. Then when you do a 'git diff' on one of them, you'll see that the only change was in the executable bit in the permissions, ie

$ git diff scripts/e2e-test.sh
diff --git a/scripts/e2e-test.sh b/scripts/e2e-test.sh
old mode 100755
new mode 100644


Tuesday, 1 April 2014

Mockito - don't use @InjectMocks if your constructor will be calling methods on your injected mocks

I had this:

@Mock
MessageSource mockMessageSource;

@InjectMocks
PhoneNumberUtil phoneNumberUtil;


@Before
public void setup() {

    MockitoAnnotations.initMocks(this);


    when(mockMessageSource.getMessage(eq("first.key"), (Object[]) eq(null), anyString(),eq(Locale.getDefault()))).thenReturn("This is a default message");
    when(mockMessageSource.getMessage(eq("second.key"), (Object[]) eq(null), anyString(),eq(Locale.getDefault()))).thenReturn("second Value");


}


Where


public PhoneNumberUtil(MessageSource messageSource) {
    this.firstValue = messageSource.getMessage("first.key"), null, FIRST_DEFAULT_VALUE, Locale.getDefault());
    this.secondValue = messageSource.getMessage("second.key"), null, SECOND_DEFAULT_VALUE, Locale.getDefault());
}



I was running my unit test but wondering why the fields "firstValue" and "secondValue" were still coming out as null.

I already mocked the messageSource.getMessage() calls. Why weren't my mocks getting called??

Then I realised: the when().thenReturn() calls weren't getting called until AFTER PhoneNumberUtil was already initialized!


I was using @InjectMocks and once the line

MockitoAnnotations.initMocks(this);

was called, phoneNumberUtil would already get initialised with mockMessageSource. But at that point, mockMessageSource isn't setup to do anything yet.

So the fix was to do this in my setup()



@Mock
MessageSource mockMessageSource;

PhoneNumberUtil phoneNumberUtil;

@Before
public void setup() {

    MockitoAnnotations.initMocks(this);


    when(mockMessageSource.getMessage(eq("first.key"), (Object[]) eq(null), anyString(),eq(Locale.getDefault()))).thenReturn("This is a default message");
    when(mockMessageSource.getMessage(eq("second.key"), (Object[]) eq(null), anyString(),eq(Locale.getDefault()))).thenReturn("second Value");

    phoneNumberUtil = new PhoneNumberUtil(mockMessageSource);

}


If you need to make a call on a mocked dependency in the constructor of the class you're testing, then you can't use the @InjectMocks pattern.

You need to create the class you are testing using code, not annotations, using constructor injection to pass in the mocked dependencies, and you need to create it after you've mocked the methods being called in the constructor.


Friday, 14 March 2014

Prevent Googlebot from crawling some links, but still have them useable by the user

WHAT:

Prevent Googlebot from crawling some links, so that other more
important links on our page are given priority and indexed faster


HOW:

1. remove the link, replace with "#" so it's still a valid HREF
2. Put the value as data attribute, ie, data-goto
3. Reverse the value because if we had data-goto="/productlist.html",
Googlebot would still crawl it.
Instead we have data-goto="lmth.tsiltcudorp/"
4. On loading the page, run a javascript to go through all the links
that have this attribute, reverse the string and place it in the
"href" attribute. Googlebot can't run javascript so it never sees the
HREF values in there.

RETURNED BY SERVER

<a class="unseen-link" href="#" data-goto="lmth.tsiltcudorp/">Product List</a>


SEEN BY USER

<a class="unseen-link" href="/productlist.html"
data-goto="lmth.tsiltcudorp/">Product List</a>



function prepareMissingLinks() {
var stringReverse = function(string) {
return string.split('').reverse().join('');
};
var $hiddenLink = $('.unseen-link');

$hiddenLink.each(function() {
$(this).attr("href", stringReverse($(this).data('goto')));
});
}



I had an earlier implementation of this using the hover event but that
doesn't work for touchscreen devices. This works on desktop and
mobile, and is also simpler.

Wednesday, 26 February 2014

How to change extension of multiple files in Linux?

When files are in same folder:

rename 's/.abc$/.edefg/' *.abc


Recursively rename files:

# Bash
# Also requires GNU or BSD find(1)
# Recursively change all *.foo files to *.bar

find . -type f -name '*.foo' -print0 | while IFS= read -r -d '' f; do
mv -- "$f" "${f%.foo}.bar"
done



From:
http://askubuntu.com/questions/35922/how-to-change-extension-of-multiple-files-from-command-line

Also see:

http://mywiki.wooledge.org/BashFAQ/030

Wednesday, 12 February 2014

@RetryOnFailure annotation using Aspect from JCABI library

Use this annotation to make repeated calls on failure for an idempotent method

http://www.jcabi.com/jcabi-aspects/annotation-retryonfailure.html

Validate user-inputted URLs using Google Safe Browsing API

Use this API to get a database of URLs from Google and verify them
locally. They also have an earlier version of the API but you need to
make a remote call. This is better as the client is the only one that
knows about the URLs it is verifying.

https://developers.google.com/safe-browsing/developers_guide_v2

Thursday, 6 February 2014

Notes: Example of image data embedded in HTML

This is a div that appears on the Onion above an article when you've
reached 5 articles already, asking you to subscribe. The image
information is embedded in base64 on the div itself.


<div style="background-image:
url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyJpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMC1jMDYwIDYxLjEzNDc3NywgMjAxMC8wMi8xMi0xNzozMjowMCAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENTNSBNYWNpbnRvc2giIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6RDhCQzBDREZCQ0ZGMTFFMEIxQkFCQ0MxOEQzMzc5NTEiIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6RDhCQzBDRTBCQ0ZGMTFFMEIxQkFCQ0MxOEQzMzc5NTEiPiA8eG1wTU06RGVyaXZlZEZyb20gc3RSZWY6aW5zdGFuY2VJRD0ieG1wLmlpZDpEOEJDMENEREJDRkYxMUUwQjFCQUJDQzE4RDMzNzk1MSIgc3RSZWY6ZG9jdW1lbnRJRD0ieG1wLmRpZDpEOEJDMENERUJDRkYxMUUwQjFCQUJDQzE4RDMzNzk1MSIvPiA8L3JkZjpEZXNjcmlwdGlvbj4gPC9yZGY6UkRGPiA8L3g6eG1wbWV0YT4gPD94cGFja2V0IGVuZD0iciI/PoOauxEAAAALSURBVAgdYzA+AwABNQEAGVbmvQAAAABJRU5ErkJggg%3D%3D);
z-index: 99998; position: absolute; top: 0px; left: 0px; width: 100%;
height: 3198px;"></div>

Tuesday, 4 February 2014

Java: (Spring) Getting subset of a list for paged display

PagedListHolder - one of those Spring classes that you wish you've
been using for the past 10 years

Given a
1. list of items
2. page number and
3. number of items per page

Return the part of the list to be displayed on the page


PagedListHolder<PopularSearch> pagedListHolder = new
PagedListHolder<PopularSearch>(sourceList);
pagedListHolder.setPage(pageNumber);
pagedListHolder.setPageSize(itemCountPerPage);

List<PopularSearch> tmp = pagedListHolder.getPageList();

Friday, 31 January 2014

Doubleclick for Publishers reference material

From: https://productforums.google.com/forum/#!category-topic/dfp/getting-started/208IT9kC6Xo

For Premium

DFP Premium Help Center
https://support.google.com/dfp_premium/

Please remember that are two main ways to contact DFP. There is a
Contact Us link on all DFP Premium support page (near the upper right
hand part of the page). There is also a Report a Bug link in your DFP
account (also in the upper right hand corner of your page).

Getting Started Guide (high level overview)
https://support.google.com/dfp_premium/answer/184981

Training
https://support.google.com/dfp_premium/answer/3419426

Partner Directory
https://support.google.com/dfp_premium/answer/2616938

DFP Training Videos:
http://www.youtube.com/dfp

Release Notes
https://support.google.com/dfp_premium/answer/179039


Other Resources

Google also provides additional tools to webmasters to help you track
traffic and improve your search rankings. If you have not signed up
already, you might want to at least take a quick look at them.

Google Analytics
http://www.google.com/analytics/

Google Webmaster Tools
http://www.google.com/webmasters/


Webinars

Google has been releasing quite a few webinars that people maybe
interested in. While not always specific to DFP, many of them are
helpful for webmasters and advertising in general.

You can register for Google Webinars here:
http://www.google.com/ads/experienced/webinars.html

Or use their Calendar to see upcoming Webinars
https://www.google.com/calendar/embed?src=google.com_fqpk56cl9ck36np1ip263m2hks%40group.calendar.google.com

Javascript: Finding the viewport width,

Useful for responsive design, determining same max-width used in @media queries

var windowWidth = window.innerWidth ||
document.documentElement.clientWidth || document.body.clientWidth;

Based on: http://andylangton.co.uk/blog/development/get-viewport-size-width-and-height-javascript


"The responsive viewport breakpoint "staircase" in my opinion becomes:

320px, 480px, 603px, 768px, 966px, 1024px"

See: http://www.hardweb.com.au/nexus7viewportportrait603x797landscape966x444.html

Also read:

http://alistapart.com/article/vexing-viewports


Been working recently on Google DFP tag code, so keeping these references:

http://exisweb.net/how-to-use-google-adsense-on-a-responsive-website

https://productforums.google.com/forum/#!msg/dfp/gxHN91Z7PoI/yC14WsR0KoMJ

http://stackoverflow.com/questions/15423189/changing-ad-size-based-on-browser-width-in-dfp

http://stackoverflow.com/questions/15452905/adding-a-browser-width-component-to-ad-slots




<!DOCTYPE html>
<html>
<head>
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
<title> - jsFiddle demo</title>
<script type='text/javascript'
src='https://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js'></script>
<link rel="stylesheet" type="text/css" href="/css/result-light.css">
<style type='text/css'>
</style>


<script type='text/javascript'>//<![CDATA[
$(window).load(function(){
$("#showValue").click(function () {
var windowWidth = window.innerWidth ||
document.documentElement.clientWidth || document.body.clientWidth;

$("#widthLabel").text(windowWidth);
$("#windowinnerWidth").text(window.innerWidth);
$("#documentdocumentElementclientWidth").text(document.documentElement.clientWidth);
$("#documentbodyclientWidth").text(document.body.clientWidth);
$("#viewportHeight").text($(window).height());

});
});//]]>

</script>


</head>
<body>
<p>Width: <span id="widthLabel"></span>

<br/>window.innerWidth: <span id="windowinnerWidth"></span>

<br/>document.documentElement.clientWidth: <span
id="documentdocumentElementclientWidth"></span>

<br/>document.body.clientWidth: <span id="documentbodyclientWidth"></span>

<br/>$(window).height(): <span id="viewportHeight"></span>
</p>
<input id="showValue" type="button" value="Show Width" />
</body>


</html>

Wednesday, 15 January 2014

TIL: Hibernate JPA NamedNativeQuery declaration requires a "resultClass" even for update/delete operations

I was writing some JPA code (Hibernate implementation) that used
NamedNativeQuery

and kept getting this when I ran the webapp in Tomcat:

nested exception is org.hibernate.cfg.NotYetImplementedException: Pure
native scalar queries are not yet supported

The exception was from an unrelated class but I suspected that this
was caused by changes I made.

According to this:

http://jdevelopment.nl/hibernates-pure-native-scalar-queries-supported/

resultClass is required for all NamedNativeQuery, even the ones that
don't return them, because of a longstanding BUG in Hibernate.
Apparently the bug was fixed as of Hibernate 4.2 but we're still on
3.6 so upgrading is not really an option.

Thursday, 31 October 2013

Joda Time - handling of end of February when DateTime.plusMonths() is called

Overheard a colleague at work with an issue re: February and got
curious enough to see what Joda-Time does in handling this scenario:

// if current date is 31st, how will joda-time handle setting month to february?
dt = new DateTime();
println "now: " + dt.toString();
futureDt = dt.plusMonths(4);
println "4 mos in future: " + futureDt.toString();

OUTPUT

now: 2013-10-31T15:29:53.628+11:00
4 mos in future: 2014-02-28T15:29:53.628+11:00

Nice.

The Groovy Shell functionality within IntelliJ IDEA makes quick
playing around like this a breeze!