tag:blogger.com,1999:blog-24150418625449098562024-03-13T03:46:19.836-07:00FlowstopperFabian Kessler: Dreamer by day, programmer by night. <br>My nightly experiences as a programmer that I find worth sharing.<br>
My employer's site: <a href="http://www.nameapi.org">NameAPI.org</a> web services for names (check it out)
Anonymoushttp://www.blogger.com/profile/16815999018553645136noreply@blogger.comBlogger35125tag:blogger.com,1999:blog-2415041862544909856.post-42519851906420235532015-09-11T02:59:00.001-07:002015-09-11T02:59:44.124-07:00IntelliJ Feature Request: Find Escaped Strings<br />
IntelliJ has some automatic String escaping built in.<br />
<br />
<h3>
IntelliJ automatic String escaping on copy/paste</h3>
<br />
<i>Example: pasting TO IntelliJ</i><br />
Write some code:<br />
<span style="color: #444444;"><span style="font-family: "Courier New",Courier,monospace;">String s = "";</span></span><br />
Then paste this sequence between the double quotes: <span style="color: #444444;"><span style="font-family: "Courier New",Courier,monospace;"><li><a href="#"></span></span><br />
What you have is:<br />
<span style="color: #444444;"><span style="font-family: "Courier New",Courier,monospace;">String s = "<li><a href=\"#\">";</span></span><br />
IntelliJ intelligently escaped the double quotes for you.<br />
<br />
<i>Example: copying FROM IntelliJ</i><br />
Select the string literal above, including the surrounding double quotes (<span style="color: #444444;"><span style="font-family: "Courier New",Courier,monospace;">"<li><a href=\"#\">"</span></span>), and paste it into Notepad. What you get is exactly that.<br />
Select the string content, excluding the double quotes (<span style="font-family: "Courier New",Courier,monospace;"><span style="color: #444444;"><li><a href=\"#\">"</span></span>), and paste it into Notepad. What you get is the string unescaped: <span style="font-family: "Courier New",Courier,monospace;"><span style="color: #444444;"><li><a href="#"></span></span><br />
<br />
That's pretty smart, and most always what I want.<br />
<br />
<br />
<h3>
IntelliJ automatic String escaping on search</h3>
<br />
Example: ctrl-alt-f searching for <span style="font-family: "Courier New",Courier,monospace;"><span style="color: #444444;"><li><a href="#"></span></span> does <b>not find</b> our code <span style="color: #444444;"><span style="font-family: "Courier New",Courier,monospace;">String s = "<li><a href=\"#\">";</span></span><br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="http://4.bp.blogspot.com/-MtDWbfpeRJ0/Vexwerf0v7I/AAAAAAAAAPM/r_578Vm_Jh4/s1600/intellij-find-escaped-strings.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="http://4.bp.blogspot.com/-MtDWbfpeRJ0/Vexwerf0v7I/AAAAAAAAAPM/r_578Vm_Jh4/s1600/intellij-find-escaped-strings.png" /></a></div>
<br />
<br />
Here's an idea for the IDEA team: how about a checkbox "Find escaped strings"?<br />
Of course, in practice it'll get a bit more complicated than just handling the double quotes. Depending on the programming language. JavaScript has single quotes, there are regular expression and SQL escapes, etc. And I'd want to be careful with the search-and-replace functionality (or just not offer this feature there).<br />
<br />
<br />
<h3>
Conclusion </h3>
The Java editor has already proven that it can handle the escapes to the advantage of the developer. So why not extend to search?<br />
<br />
Anonymoushttp://www.blogger.com/profile/16815999018553645136noreply@blogger.com0tag:blogger.com,1999:blog-2415041862544909856.post-79649389778632868072015-06-17T15:46:00.000-07:002015-06-17T15:46:34.521-07:00French OVH vs German Hetzner: the Stereotypes Are Alive <span style="font-size: large;">This is an open letter describing my experiences and offering some suggestions to the French hosting company OVH.</span><br />
<br />
I have had 2 cheap VPS at OVH for a year now. (And services from Hetzner for longer.)<br />
<br />
Every once in a while, one of the virtual private servers at OVH is unreachable. Today was such a case; no information from OVH announcing the downtime, no alert while offline. My own monitoring shows one VPS unreachable for 1.5 hours in the afternoon. 1.5 hours. I wonder what it is that takes so long to be fixed.<br />
<br />
So let's check the OVH status:<br />
<br />
<a href="http://4.bp.blogspot.com/-z24ezIvxcHw/VYGlMrTncQI/AAAAAAAAAOY/G6p4IQvYmW0/s1600/status.ovh.de_%2Bis%2Bnot%2Bavailable.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="http://4.bp.blogspot.com/-z24ezIvxcHw/VYGlMrTncQI/AAAAAAAAAOY/G6p4IQvYmW0/s1600/status.ovh.de_%2Bis%2Bnot%2Bavailable.png" /></a><i> </i><br />
<i>D'Accord. </i><br />
<br />
I prefer how the competing German ISP Hetzner has a completely separate domain name for the status page at <a href="http://www.hetzner-status.de/">http://www.hetzner-status.de/</a> because you know maybe something is wrong with the primary domain or DNS record or whatever and then hell breaks loose.<br />
<br />
Quite a while later I was able to get that page, here's how it looks:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="http://4.bp.blogspot.com/-iBloFcYEX0o/VYG0brxZsqI/AAAAAAAAAOo/y-0Tt2vLE7k/s1600/ovh-status.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="515" src="http://4.bp.blogspot.com/-iBloFcYEX0o/VYG0brxZsqI/AAAAAAAAAOo/y-0Tt2vLE7k/s640/ovh-status.png" width="640" /></a></div>
<br />
<br />
The colors look scary, issues everywhere. But that's probably explainable by the large size of the ISP.<br />
<br />
Although it's not visually visible, I have clicked and therefore filtered by the VPS category on the screen.<br />
<br />
Unfortunately, with the information given in the table, I am not able to identify by which of the many cases my VPS could be affected. So let's log in to the admin panel of my hosting account.<br />
<br />
There is no alert message here either. After a while I'm able to find charts that prove the downtime, and they indicate a restart:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="http://3.bp.blogspot.com/-iJaAFr4zDMY/VYG2YFeecRI/AAAAAAAAAO0/CVov2eP_FBs/s1600/server-offline.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="http://3.bp.blogspot.com/-iJaAFr4zDMY/VYG2YFeecRI/AAAAAAAAAO0/CVov2eP_FBs/s1600/server-offline.png" /></a></div>
<br />
<br />
The CPU was off and then a bump (boot). Ram was off too, and traffic was zero.<br />
<br />
<h3>
Recommendation to OVH:</h3>
<ol>
<li>The backend tells me the VPS is in zone vz-rbx2-005. If you'd list that on the status page in the table, I'd have a chance identifying issues that affect me.</li>
<li>Even better, show the issue in the customer control panel overview, and on the VPS overview page. With a nice history of all past issues.</li>
<li>If it was a predictable/planned downtime, inform before. Hetzner does this. The last notice was about replacing a Switch. It came 1 week (!) before. And after all there was 0 downtime. German planning.</li>
<li>During downtime, send an info pointing to the task. At least if it is not resolved quickly.</li>
<li>After prolonged downtime (1.5 hours!) and an OS reboot (!) send an info maybe? That it happened, what the cause was, and what you intend to do in the future to prevent it. After finishing your croissant maybe.</li>
</ol>
<br />
Regarding email, OVH used to send alerts. There was a period with annoying alerts for high CPU load caused by Rsyslog on Ubuntu. OVH fixed it and they are gone. Other than that, I have not received alerts.<br />
<br />
Out of curiosity, let's check the uptime of my second OVH virtual server.<br />
<br />
<span style="font-family: "Courier New",Courier,monospace;">> uptime</span><br />
<span style="font-family: "Courier New",Courier,monospace;">> up 2 days, 54 min, 1 user, load average: 0.08, 0.03, 0.01</span><br />
<br />
<i>Quelle surprise!</i> Considering that I have not touched this server in months...<br />
<br />
<br />
<h3>
Final words</h3>
I have no affiliation with any of the 2 providers, other than being a customer with both.<br />
<br />
At OVH, everything feels a bit "French". The admin panels; confusing, one redirecting to the next and back. Parts are translated, parts appear in Français. The website. The payment process. I would not host anything uptime critical there. <br />
<br />
Hetzner is not perfect. In a subjective classification I'd give them a "good to very good" - for my needs. Great value for the price. And I don't see anyone else on the horizon with a better service offering at competitive costs.<br />
<br />
If you need a place for a game server, or other leet services, please choose OVH with their DDoS protection. I'd rather have you not too close to my important machines ;-)<br />
<br />
If anyone else asks, then I personally recommend <a href="https://www.hetzner.de/en/" target="_blank">Hetzner</a>.<br />
<br />Anonymoushttp://www.blogger.com/profile/16815999018553645136noreply@blogger.com1tag:blogger.com,1999:blog-2415041862544909856.post-37100155866224979552015-05-05T02:56:00.001-07:002015-05-05T02:56:49.210-07:00Interpretations of end-of-file, and Linux ad hoc open heart surgery<span style="font-size: large;">Today's occasional Linux sysadmin task for a Java developer (me) is to loop all lines in a text file and run a task based on each. Can't be that hard, can it? </span><br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="http://1.bp.blogspot.com/-nhx0LBvNx5c/VUhlD3HbsTI/AAAAAAAAAOE/RlxBF6aJh18/s1600/google-bash-loop-over-lines-in-file.png" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"><img border="0" src="http://1.bp.blogspot.com/-nhx0LBvNx5c/VUhlD3HbsTI/AAAAAAAAAOE/RlxBF6aJh18/s1600/google-bash-loop-over-lines-in-file.png" /></a></div>
Off we go the usual route: <br />
<br />
1) Google the task. Aha, looks like a common requirement.<br />
<br />
2) Find the usual stackoverflow, askubuntu, superuser and some other forums and blog posts.<br />
<br />
And the offered snippets looks simple and clear:<br />
<br />
<blockquote>
<span style="color: #b45f06;"><span style="font-family: "Courier New",Courier,monospace;">while read line; do</span></span><br />
<span style="color: #b45f06;"><span style="font-family: "Courier New",Courier,monospace;"> echo "line is: $line"</span></span><br />
<span style="color: #b45f06;"><span style="font-family: "Courier New",Courier,monospace;">done </my/file.txt</span></span></blockquote>
<br />
or alternatively <br />
<br />
<blockquote>
<span style="color: #b45f06;"><span style="font-family: "Courier New",Courier,monospace;">cat /my/file.txt | while read line; do</span></span><br />
<span style="color: #b45f06;"><span style="font-family: "Courier New",Courier,monospace;"> echo "line is: $line"</span></span><br />
<span style="color: #b45f06;"><span style="font-family: "Courier New",Courier,monospace;">done</span></span></blockquote>
<br />
And it works! Mostly. Occasionally the last line is missing. This happens when there is no trailing blank line in the file. A detailed explanation to that problem is here: <a href="http://stackoverflow.com/questions/12916352/shell-script-read-missing-last-line">http://stackoverflow.com/questions/12916352/shell-script-read-missing-last-line</a><br />
<br />
So finally here's a snipped that works for all files:<br />
<br />
<blockquote>
<span style="color: #38761d;"><span style="font-family: "Courier New",Courier,monospace;">cat /tmp/testfile | while read line || [ -n "$line" ]; do</span></span><br />
<span style="color: #38761d;"><span style="font-family: "Courier New",Courier,monospace;"> echo "line is: $line"</span></span><br />
<span style="color: #38761d;"><span style="font-family: "Courier New",Courier,monospace;">done</span></span></blockquote>
<h3>
</h3>
<h3>
Fragile solutions</h3>
<br />
This most recent experience is very much like so many others I've had with Linux system administration tasks. Faced with a seemingly simple problem, I find many solutions, but there are hidden pitfalls. <b>An implemented solution must be stable, and not depend on assumptions and best practices and current conditions.</b> That's what we practice in programming. Why not in system administration?<br />
<br />
In this case one can argue that a text file must end with a newline character. Some pro arguments:<br />
<ul>
<li>Apparently there's some C specification <i>(from a time before you were born)</i>. </li>
<li>When storing a text file in the Linux editor vi it's done, the newline is appended. <i>(vi also being from the 70s)</i></li>
<li>When writing a file by code there's usually a println(string) method. This also results in the trailing blank line.</li>
</ul>
But there's also contra:<br />
<ul>
<li>Files can come from other sources. For example from a Windows Notepad++ and the newline can be missing. </li>
<li>Or if the file is generated by a program, it's easy for a developer to change some logic and remove the trailing newline, without being aware of the consequences.</li>
<li>In PHP, if you include a script file that ends with a newline after the closing "<span style="font-family: "Courier New",Courier,monospace;">?></span>" end tag, it sends white space to the client, and prevents you from adding <a href="https://php.net/manual/en/function.header.php" target="_blank">header()</a>s. You must break that C standard. (PHP is written in C you see ...)</li>
<li>It just sounds like a silly specification, way too easy to break, and not necessary. </li>
</ul>
Ask yourself the question: if you'd write the specification where a file ends, would you choose "the last newline character" or "where the last bit ends"?<br />
<br />
<h3>
<br />
</h3>
<h3>
Stackoverflow helps but pay attention to the comments</h3>
<br />
Another case I recently run into was with a Linux cleanup process. The task definition was simple again: "delete all but the most recent 5 files from a folder matching a file name pattern". An accepted solution is here <a href="http://stackoverflow.com/questions/25785/delete-all-but-the-most-recent-x-files-in-bash">http://stackoverflow.com/questions/25785/delete-all-but-the-most-recent-x-files-in-bash</a> with plenty of upvotes. The problems, which are not mentioned in the answer:<br />
<ul>
<li>If there are only 5 or less files, <b>it deletes them all</b></li>
<li>It doesn't work if there are folders present</li>
<li>It won't work with file names with spaces</li>
</ul>
In time I've learned to pay attention to the user's comments. And one saying <i>"This one fails if there are no files to delete."</i> made me suspicious. Again, it doesn't fail, the command goes through like a knife cuts through soft butter... no complaint, just removes them all.<br />
<br />
Imagine this scenario (mine): It's the backup folder, and the last 5 backups should be kept. For some reason the backup process fails, and no new files are created. The separate cleanup script still runs nightly and removes all but the last 5 files. With this little glitch in the script you'll end up having no backup at all.<br />
<br />
<br />
<h3>
All ad hoc, open heart surgery</h3>
<br />
Linux sysadmin is not in my job description. I see the situation from a bit of distance. What I realize is that programming has come a long way in the last 20 years. Open source libraries are used instead of quickly hacked untested functions. Everything is version controlled. Nothing gets deployed without thorough testing. Pair programming. Code reviews.<br />
<br />
System administration? Still the same. Copy pasting some commands found on the internet. On production machines. Works? No? Try another one. Works? Fine. Document changes? Nah. <br />
<br />
Any sysadmin of +5 years who hasn't locked himself out of an ssh server by misconfiguring sshd or iptables in da house please stand up.<br />
<br />
<br />
<h3>
Conclusions</h3>
<br />
It's easier these days to find answers and solutions on the internet thanks to the Q&A format of Stack Exchange. But more than in programming, in sysadmin the comments and secondary answers are important to read.<br />
<br />
At the company we stick to some simple rules<br />
<ul>
<li>Changes made to machines must to be documented. Remine for tasks and especially the Wiki works well.</li>
<li>Mission critical machines have a sibling.</li>
<li>System changes on production machines must be applied one at a time, with a few days in between.</li>
<li>Most apps run on VMs. It's not like git but it's as good as it gets for the time being.</li>
</ul>
<br />
<br />
<h3>
End-of-file Marker </h3>
<br />
Back to the initial task for looping a file to the end: when reading mission critical changeable files by Java we use an end of file marker "eof". If the file ends with that line then we can be sure the file was read completely. If not, then it could be broken, and the program throws an exception.<br />
<br />
<br />
<br />
<br />
<br />Anonymoushttp://www.blogger.com/profile/16815999018553645136noreply@blogger.com2tag:blogger.com,1999:blog-2415041862544909856.post-85877119104487694632015-04-05T06:00:00.000-07:002015-04-05T06:00:28.097-07:00Is that Googlebot user agent really from Google?<span style="font-size: large;">How do you know if the client identifying as <i>Googlebot </i>is actually from <i>Google</i>? And <i>Bingbot</i>? And all the others? On <a href="https://github.com/optimaize/webcrawler-verifier" target="_blank">Github</a> there's a newly published library, written in <i>Java </i>with <i>Maven </i>that performs the checks for you. And why would you care?</span><br />
<br />
There are different kinds of visitors to your website. Some webmasters don't mind any of the traffic, don't discriminate, and let them all pass. Others block or at least limit or throttle some of the requests. But why?<br />
<blockquote class="tr_bq">
<span style="font-size: small;">In the end it all boils down to the visitors you want, and those that you don't want. Those that bring you potential benefit, and those that only cost you traffic, and possibly worse duplicate your site content, collect email addresses, or align your site with bad reputation.</span></blockquote>
<br />
There are 2 kinds of users visiting your site. Humans, and robots. This article (and the software) is about the bots only.<br />
<br />
The robots can be classified as follows:<br />
- search engine crawlers: googlebot, bingbot, baiduspider, ...<br />- other purpose crawlers: archive.org_bot, ahrefsbot, ... <br />- custom crawlers: data scrapers, email harvesters, offline readers, ...<br />
<br />
<h3>
Search engines</h3>
Search engines operate crawlers to feed their indexes. You generally want to let these through because they drive visitors to your site. The more pages they index, the better for you.<br />
<br />
However, there may be exceptions. Dan Birken has an <a href="http://danbirken.com/seo/2013/10/17/who-exactly-is-crawling-my-site.html" target="_blank">interesting read</a> on this: Baidu is a greedy spider that possibly gives you nothing in return, depending on your target audience.<br />
<br />
And these days search engines don't only operate text search, there is also images, videos, and more. Some sites may have not interest in appearing in the Google image search, and therefore <a href="https://support.google.com/webmasters/answer/35308?hl=en" target="_blank">lock out the Googlebot-Image crawler</a>.<br />
<br />
<h3>
Other purpose crawlers</h3>
The web archive is a nice thing. Some webmasters choose to not have a pubic history of their site, and block the bot.<br />
<br />Commons Crawl is another one that some don't mind, and others forbid, depending on their site content.<br />
<br />
Blocking blood suckers including the ahrefsbot, a6, ADmantX and more has a larger fan base.<br />
<br />
And finally blocking email harvesters should be on every webmaster's menu.<br />
<br />
<h3>
Custom crawlers</h3>
This is software from the shelf or even custom tailored to grab parts or your entire website. These bots are not run from a specific website or service provider. Any script kiddie can fire them up. If you operate a blog, on a shared hosting with unlimited traffic, you probably don't mind. In the best case you end up being listed on some blogging directory. In a worse case parts of your content appear remixed on a seo index spammer's fake portal, alined with links to sites of bad reputation.<br />
<br />
<h3>
The problem: impersonators</h3>
<div class="separator" style="clear: both; text-align: center;">
<a href="http://1.bp.blogspot.com/-__4llCavCIM/VSCr-M6BCyI/AAAAAAAAANw/qHAehvDVfig/s1600/evil-webcrawler-impersonator.jpg" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"><img border="0" src="http://1.bp.blogspot.com/-__4llCavCIM/VSCr-M6BCyI/AAAAAAAAANw/qHAehvDVfig/s1600/evil-webcrawler-impersonator.jpg" /></a></div>
As long as all visitors identify with the correct and honest user-agent they are, the task is simple. You define in your <a href="http://en.wikipedia.org/wiki/Robots_exclusion_standard" target="_blank">/robots.txt</a> which crawlers are allowed. Task accomplished. But as we all know (that's where you nod), the user-agent is just and http header field that anyone can modify. Even and especially from PHP. Pun intended.<br />
<br />
Some masquerade as a common web browser, eg Chrome or Firefox. It's a bit more tricky to identify these, but there are ways.<br />
<br />
The well known spider trap trick can help: a link in the html to /dont-go-here that humans can't see thanks to CSS, and that nice bots won't follow because you forbid the area in the robots.txt. Then, if someone hits that page, he's either a vampire bot, or a curious web developer who views the source, or a blind person agnostic to CSS.<br />
<br />
Other ideas are limiting the amount of web traffic per user (ip/network, session). Some sites implement a Captcha after too many requests per time.<br />
<br />
Other custom crawlers impersonate as one of the well known spiders; Googlebot. Chances are there are no request limits in place. After all who wants to risk being deleted from the Google index.<br />
<br />
<h3>
The solution: spider identification</h3>
That's where this software library comes in. The users that identify as one of the top search sites need to be verified.<br />
<br />
For a long time the way of identification used to be by maintaining ip lists. Good news! For many years the <a href="https://support.google.com/webmasters/answer/80553" target="_blank">major</a> <a href="http://www.bing.com/webmaster/help/how-to-verify-bingbot-3905dc26" target="_blank">players</a> have been supporting and advocating a zero-maintenance system. It works by validating the ip with a reverse and forward DNS lookup.<br />
<br />
For those search engines and sites that don't support this method, identification still needs ip lists.<br />History has shown that this way is problematic. The ip ranges change, the lists always lag behind. Search for lists on Google and you'll find totally outdated lists in the tops. Lists that still mention msnbot (now bingbot) and Yahoo! Slurp (now defunct).<br />
<br />
A library, used as a dependency by many developers, hosted on Github where it's easy to contribute, hopefully solves that problem.<br />
<br />
<h3>
Actions taken on spoofers</h3>
What action you take if verification returns negative is up to you. Block the user, throttle the connection, display a Captcha, alert the webmaster.<br />
<br />
You can run the verification check live as the request comes in. There's an initial price you pay on the first request for the DNS lookups. Or you can run a watchdog on your webserver's logfiles and take action a bit delayed.<br />
<br />
<h3>
Call for action</h3>
Head over to <a href="https://github.com/optimaize/webcrawler-verifier">https://github.com/optimaize/webcrawler-verifier</a> and replace your custom Googlebot verification hack, using outdated ip lists, with this dependency.<br />
<br />
Anonymoushttp://www.blogger.com/profile/16815999018553645136noreply@blogger.com0tag:blogger.com,1999:blog-2415041862544909856.post-31013923749766884402015-01-29T05:14:00.001-08:002015-01-29T05:14:07.512-08:00Manual PHP Installation on Windows: for Masochists only?<br />
<span style="font-size: large;">Yesterday I needed to quickly apply some changes to a PHP library hosted on GitHub. I haven't used PHP since I switched to a new PC, so there's some setup to do. But for me as a former PHP developer it won't take too long, will it? </span><br />
<br />
This article won't teach you how to install PHP on Windows. It illustrates my experience, the troubles I went through, and suggests improvements to the process.<br />
<br />
<br />
<h3>
The requirements: PHP and PHPUnit </h3>
<br />
Because I should test my code before committing, I need a
runtime environment. IntelliJ IDEA (the big brother of PhpStorm) is here
already. What's left is PHP and PHPUnit. The library to lay my hands on doesn't require web. No web server, just scripting. <br />
<br />
<br />
<h3>
Step 1: Install PHP</h3>
<h4>
</h4>
<h4>
Choosing the right version </h4>
Visiting php.net, I learn that the latest releases are <i>5.4.37</i>, <i>5.6.5</i> and <i>5.5.21</i>. Hrm. What to choose? The downloads page <a href="http://php.net/downloads.php">http://php.net/downloads.php</a> tells me that the current stable is <i>5.6.5</i>, so probably that. Just to be sure, I'd like to know a bit more about the compatibility and feature sets of these versions. On the PHP page, including the documentation, I don't find that kind of data. Wikipedia is my friend: <a href="http://en.wikipedia.org/wiki/PHP#Release_history">http://en.wikipedia.org/wiki/PHP#Release_history</a> <b>so the 5.6 branch it is</b>.<br />
<br />
There are more choices to be done on <a href="http://windows.php.net/download#php-5.6">http://windows.php.net/download#php-5.6</a><br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="http://4.bp.blogspot.com/-7-G1-NdxkzM/VMoBLqm9ugI/AAAAAAAAAM4/jaOGHU7KWy0/s1600/PHP%2BFor%2BWindows_%2BBinaries%2Band%2Bsources%2BReleases.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="http://4.bp.blogspot.com/-7-G1-NdxkzM/VMoBLqm9ugI/AAAAAAAAAM4/jaOGHU7KWy0/s1600/PHP%2BFor%2BWindows_%2BBinaries%2Band%2Bsources%2BReleases.png" height="601" width="640" /></a></div>
<br />
32 or 64 bit? Thread safe or not? Zip or Debug Pack? Or download source code?<br />
Ah, there's a helping hand on the left "<i>Which version do I choose?</i>"<br />
Since there isn't an easy answer, I go with the rule-out logic to limit the choices.<br />
<ol>
<li>IIS? no.</li>
<li>Apache? no.</li>
<li>VC9 and VC11? There's only VC11 for PHP 5.6.5, so I'll need to install that.</li>
<li>Regarding TS vs NTS since I want CLI I'll go with NTS.</li>
<li>x86 vs x64, don't want experimental, so x86.</li>
</ol>
I guess we have a winner: php-5.6.5-nts-Win32-VC11-x86.zip<br />
<br />
<h4>
Installing it</h4>
After extracting the archive, the novice user might be looking for a setup or install exe. I also checked quickly because years passed by since I had last installed this thing. But no luck. So the good old install.txt file needs to be consulted. <b>And by old I mean old.</b> It seems that this file is an accumulated pile of information that grew in all directions. It's almost 2000 lines long. It explains how to handle PHP 4 <span style="font-size: small;">throughout the file in 26 places. PHP 4 support ended in 2008, <b>7 years ago</b>. It's a lot to read. </span><br />
<h4>
<span style="font-weight: normal;"><span style="font-size: small;">Now at this point I wish there was an installer. There are installers. I've used them in the past. But I don't want web server integration. Just a simple scripting environment. That's what PHP is, according to the first sentence of the front page: </span></span></h4>
<blockquote class="tr_bq">
<h4>
<i><span style="font-weight: normal;"><span style="font-size: small;">PHP is a popular general-purpose scripting language that is especially suited to web development.</span></span></i></h4>
</blockquote>
<h4>
<span style="font-weight: normal;"><span style="font-size: small;">And the install instructions clearly advice me not to use an installer:</span></span></h4>
<blockquote class="tr_bq">
<h4>
<i><span style="font-weight: normal;"><span style="font-size: small;">Warning<br /><br />There are several all-in-one installers over the Internet, but none of<br />those are endorsed by PHP.net, as we believe that the manual<br />installation is the best choice to have your system secure and<br />optimised.</span></span></i></h4>
</blockquote>
<h4>
<span style="font-weight: normal;"><span style="font-size: small;">Secure and optimized... I need a development environment. </span></span> </h4>
After some ini file renaming and environment variable modification and installing VC11 redistributable (2x, took the wrong version on the first attempt) the PHP command would finally respond.<br />
<br />
<br />
<h3>
Step 2: Installing PHPUnit</h3>
<br />
There are instructions at <a href="https://www.jetbrains.com/idea/help/enabling-phpunit-support.html">https://www.jetbrains.com/idea/help/enabling-phpunit-support.html</a> and at <a href="https://phpunit.de/manual/current/en/installation.html">https://phpunit.de/manual/current/en/installation.html</a> and as always there isn't just one way to Rome.<br />
<br />
I was successful with the PEAR way in the past, and JetBrains still lists that as the first option. But as of December 2014, PHPUnit stopped supporting it. Dead end.<br />
<br />
After some trial and error with the Composer I've downloaded the latest phpunit.phar and told IntelliJ to use it. But tests wouldn't run:<br />
<blockquote class="tr_bq">
<span style="font-family: "Courier New",Courier,monospace;">PHP Fatal error: Class IDE_PHPUnit_Framework_TestListener contains 1 abstract method and must therefore be declared abstract or implement the remaining methods</span></blockquote>
According to <a href="http://stackoverflow.com/questions/22799619/intellij-idea-wont-run-phpunit-4-0-tests/22799620">http://stackoverflow.com/questions/22799619/intellij-idea-wont-run-phpunit-4-0-tests/22799620</a> I can patch my IntelliJ (ugh!) then I rather try an older PHPUnit as written here <a href="http://stackoverflow.com/questions/22531584/how-to-setup-phpunit-for-intellij-idea-13-1-on-ubuntu-13-10">http://stackoverflow.com/questions/22531584/how-to-setup-phpunit-for-intellij-idea-13-1-on-ubuntu-13-10</a><br />
<br />
Finding that was a bit of a challenge too, since <a href="https://phpunit.de/">https://phpunit.de/</a> has no link to older downloads. Here they are: <a href="https://phar.phpunit.de/">https://phar.phpunit.de/</a><br />
<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="http://3.bp.blogspot.com/-vbq1X5XQZSs/VMoSCqzBs9I/AAAAAAAAANI/T6sRkIhnMzg/s1600/IntelliJ-PHPUnit-Settings.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="http://3.bp.blogspot.com/-vbq1X5XQZSs/VMoSCqzBs9I/AAAAAAAAANI/T6sRkIhnMzg/s1600/IntelliJ-PHPUnit-Settings.png" height="344" width="640" /></a></div>
<br />
<br />
And finally the library's unit tests would execute in my IDE.<br />
<br />
<h3>
</h3>
<h3>
Conclusions</h3>
<br />
<br />
<span style="font-size: small;">Such installation and configuration procedures are the reason why I hesitate each time before finally replacing my PC, or installing a newer OS. </span><br />
<br />
<span style="font-size: small;">All in all it took me, a former PHP developer, 3 hours. Too many brain cycles were burned, too much frustration hit the desk. That was more than a flow stopper - </span><span style="font-size: small;">it marked the end of the day.</span><br />
<br />
<span style="font-size: small;">I'm sure that experienced PHP people can't relate. They know exactly how it works, and are done setting up a new machine in no time. And that's the reason for my writing... try to put yourself into the shoes of a noob.</span><br />
<br />
Does it have to be that complicated? <a href="https://www.python.org/" target="_blank">Other scripting languages</a> think not.<br />
<br />
PHP used to be the easy alternative. Looking at this mess of installation, and putting it in relation to what one expects these days and what the alternatives offer, I have some serious doubts that some beginners even manage to get started.<br />
<br />
But then again maybe it's good the way it is. <i>(If you know what I mean. That's a sarcastic comment in case you don't.)</i><br />
<br />
<h3>
</h3>
<h3>
Suggestions</h3>
<br />
<br />
For manual installation, I believe that the install instructions should be cleaned up completely. A new, shortish, simple file, without the burden of all historical facts of how things once were. But that's just applying patches and fixes.<br />
<br />
It's time for the PHP Group to provide or promote an official Windows installer. That's what would really fix the situation.<br />
<br />
<br />
<br />
Anonymoushttp://www.blogger.com/profile/16815999018553645136noreply@blogger.com0tag:blogger.com,1999:blog-2415041862544909856.post-72815239240193374632014-12-10T03:25:00.000-08:002014-12-10T03:25:35.107-08:00Graphical Visualizations in JavaDoc<span style="font-size: large;">Having code documentation is crucial for a software. It helps the developers to understand the functions and APIs. Code that is well understood is easier to improve, and therefore more likely to live on, instead of being thrown away in favor of a complete rewrite. It serves as the specification in case the code contradicts the text, and helps identifying possible bugs. </span><br />
<br />
Sometimes explaining a situation only by words is difficult and results in lengthy, hard to comprehend blathering. What options for visualizations are there?<br />
<br />
<br />
<h3>
Option 1: Images </h3>
Although most Javadoc is plain text, it permits the use of HTML formatting. <a href="http://www.oracle.com/technetwork/java/javase/documentation/index-137868.html#images" target="_blank">Images can be embedded.</a> Put them into a doc-files folder and link it:<br />
<br />
<span style="font-family: "Courier New",Courier,monospace;">/**<br /> * Visualization:<br /> * <p><img src="doc-files/my-uml-diagram.png"/></p><br /> */</span><br />
<br />
There is some cost involved in keeping this up to date; the next programmer touching the code will need to have access to the originals, and have the graph software (UML, image editor, ...) installed. This takes time.<br />
<br />
<i>Also, chances are your IDE will not show the image. </i><br />
<br />
<h3>
Javadoc history and today's use</h3>
When Javadoc was created in the early 90s, source code comments were nothing new. The pioneering feature was the auto-generation of a technical documentation directly from the source code. Prior to such documentation generators, the technical documentation used to be (badly) maintained separate from the source code. Ouch. HTML was brand new, and the build putting those files on a web server was cutting edge technology.<br />
<br />
Now, Javadoc is over 20 years old. At the time it was created, virtually all business software was closed source. Today, all software libraries we are using at the company are open source. <br />
Software projects reorganized from lengthy release cycles to release-early-release-often. And software is written in many smaller, modular pieces instead of monolithic systems. <br />
<br />
Fact is, I rarely look at Javadoc in the web browser. Most often I see it directly in the IDE. Whether it's one of our own ~40 software projects, or a library checked out from GitHub or from Maven central, or code from the JDK itself. It's just so much better to have a complete view; up to date source code and Javadoc.<br />
<br />
<br />
<h3>
Option 2: ASCII Art</h3>
An alternative to images is the good old ascii art. I personally use and recommend <a href="http://www.asciidraw.com/" target="_blank">asciidraw</a>. <br />
<br />
Here's an example:<br />
<br />
<span style="font-family: "Courier New",Courier,monospace;">/**<br /> * <pre><br /> * <br /> * +---------gn-hypo-+ +--------------gn-+<br /> * | | +------------> | |<br /> * | Osquitar | | Óscar |<br /> * | | +------> | |<br /> * +-----------------+ | +-----------------+<br /> * |<br /> * |<br /> * |<br /> * +---------gn-hypo-+ |<br /> * | | +-----+<br /> * | Osqui | +--------------gn-+<br /> * | | +-------+ | |<br /> * +-----------------+ +----> | Osgar |<br /> * | |<br /> * +-----------------+<br /> * <br /> * </pre><br /> */</span><br />
<br />
The advantages:<br />
<ol>
<li>It's quick, create a drawing within minutes.</li>
<li>It's super simple, no special knowledge required. </li>
<li>No "file originals" nor special software required.</li>
<li>Every developer can maintain it. </li>
<li>Any IDE or editor is guaranteed to display it in line.</li>
<li>Because of the technical limitations, one is forced to keep it simple and focus on the main components.</li>
</ol>
<br />
<h3>
Conclusion</h3>
You may want to consider ascii visualizations for your Javadoc the next time you're struggling with explaining a circumstance. It works great for us.<br />
<br />
<br />
<br />Anonymoushttp://www.blogger.com/profile/16815999018553645136noreply@blogger.com1tag:blogger.com,1999:blog-2415041862544909856.post-74840389354637715062014-09-22T05:04:00.000-07:002014-09-22T05:04:45.116-07:00Java SLF4J: Dynamic Log Level<h2>
In short </h2>
Problem: SLF4J doesn't support to set the log level at runtime.<br />
Solution: Use <a href="http://projects.lidalia.org.uk/lidalia-slf4j-ext/" target="_blank">Lidalia Extensions to SLF4J</a><br />
<br />
<h2>
The whole story</h2>
My Java projects that aren't older than 2008 all use the same logging setup: <a href="http://en.wikipedia.org/wiki/SLF4J" target="_blank">SLF4J</a> for the interface, <a href="http://logback.qos.ch/" target="_blank">Logback</a> for the implementation. It's a widely accepted standard with benefits.<br />
<br />
Today I had the need to dynamically set the log level at run time. Just like in Log4j logger.log(priority, message). But there's no such or similar method in the API. With one eyebrow raised I started typing into Google:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="http://2.bp.blogspot.com/-0tffnPuJBg0/VB9dgf4coFI/AAAAAAAAAMM/lFnAVGm4wOQ/s1600/google-slf4j-dynamic-log-level.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="http://2.bp.blogspot.com/-0tffnPuJBg0/VB9dgf4coFI/AAAAAAAAAMM/lFnAVGm4wOQ/s1600/google-slf4j-dynamic-log-level.png" /></a></div>
<br />
<div class="separator" style="clear: both; text-align: center;">
</div>
Ah, good, apparently I'm not the only one. There must be a simple solution. Stackoverflow already has the <a href="http://stackoverflow.com/questions/2621701/setting-log-level-of-message-at-runtime-in-slf4j" target="_blank">matching question</a>. But this time the answer is a surprise:<br />
<blockquote class="tr_bq">
<b><i>"There is no way to do this with slf4j.</i>"</b></blockquote>
That's not a statement a programmer comes across often. I shared my reaction with this popular user comment:<br />
<blockquote class="tr_bq">
<b><i>"WTF? SLF4J is heralded as the future of java's logging, and this simply use case is not supported?</i>"</b></blockquote>
The SLF4J API team has <a href="http://bugzilla.slf4j.org/show_bug.cgi?id=206" target="_blank">arguments</a> not to include these methods. <br />
<br />
I wasn't too much interested in the architectural design decisions. I just needed a quick and clean solution. And here is a nice one:<br />
<br />
<a href="http://projects.lidalia.org.uk/lidalia-slf4j-ext/" target="_blank">Lidalia Extensions to SLF4J</a> "An extension to SLF4J allowing logging at a level determined at run, rather than compile, time via a Level enum."<br />
<br />
It's small, available from Maven central, adds exactly the missing functionality, and works.<br />
<br />
<span style="font-family: "Courier New",Courier,monospace;"> <dependency><br /> <groupId>uk.org.lidalia</groupId><br /> <artifactId>lidalia-slf4j-ext</artifactId><br /> <version>1.0.0</version><br /> </dependency></span><br />
<br />
Example:<br />
<br />
<pre style="-webkit-text-stroke-width: 0px; background-color: whitesmoke; border-bottom-left-radius: 4px; border-bottom-right-radius: 4px; border-top-left-radius: 4px; border-top-right-radius: 4px; border: 1px solid rgba(0, 0, 0, 0.14902); color: #333333; display: block; font-family: Monaco, Menlo, Consolas, 'Courier New', monospace; font-size: 13px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: 20px; margin: 0px 0px 10px; orphans: auto; padding: 9.5px; text-align: start; text-indent: 0px; text-transform: none; white-space: pre-wrap; widows: auto; word-break: break-all; word-spacing: 0px; word-wrap: break-word;">import uk.org.lidalia.slf4jext.Level;
import uk.org.lidalia.slf4jext.Logger;
import uk.org.lidalia.slf4jext.LoggerFactory;
public class Example {
private static final Logger logger = LoggerFactory.getLogger(Example.class);
public static void main(String[] args) {
Level level = Level.valueOf(args[0]);
logger.log(level, "Logged at a level configured at runtime");
}
}</pre>
<br />
<br />
<br />
<br />
<br />Anonymoushttp://www.blogger.com/profile/16815999018553645136noreply@blogger.com0tag:blogger.com,1999:blog-2415041862544909856.post-32584262116200286642014-05-20T03:05:00.000-07:002014-05-20T03:05:22.126-07:00If your project is still hosted on SourceForge, I automatically assume it's dead.<br />
<span style="font-size: large;">SourceForge was the first free project hosting platform for open source software. It was immensely popular. It was the hub during the early open source years on the web - it was the GitHub of today.</span><br />
<br />
Because of its historical popularity, there is still a large amount of projects <br />
hosted there. Some are popular, some are dead - just like in any source code <br />
repository. Many developers moved their code to more modern platforms since then. <br />
At first to <a href="https://code.google.com/" target="_blank">Google Code</a>, now to <a href="https://github.com/" target="_blank">GitHub</a>. <br />
<br />
<br />
Here are 3 reasons why you should move away from SourceForge.<br />
<br />
<h3>
1) SourceForge feels dead. Many active projects moved away. </h3>
When I look for a software, I don't mind too much where it's hosted. Maturity, <br />
stability, community size and active development are the factors I look for.<br />
<br />
I don't advocate moving your whole project with source code and bugtracker every <br />
couple of years to the next hip kid on the block. <br />
<br />
But the fact that so many moved on means that what's left is probably abandoned. When I search for a software, and a GitHub and a SourceForge project comes up, I tend to click the GitHub first. Also, because of my search history, I probably get to see the GitHub links first. I'm certainly not alone here.<br />
<br />
<h3>
2) Developers have GitHub accounts</h3>
Open Source needs contributors and users. And the easiest way for developers to pitch in or file a bug report is when they already know the system and have an account. If it's complicated, I pass.<br />
<br />
<h3>
3) Scam ads: this stinks!</h3>
Here's the reason for my blog post.<br />
<br />
Once again I was downloading a (totally outdated and abandoned, but familiar and working) software that is still on SourceForge, and then I got to see this ad:<br />
<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="http://3.bp.blogspot.com/-WNeS0oJtVIA/U3ajYQPxFiI/AAAAAAAAALk/2YF1fOUCHME/s1600/sourceforge-driverupdate-ad.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="http://3.bp.blogspot.com/-WNeS0oJtVIA/U3ajYQPxFiI/AAAAAAAAALk/2YF1fOUCHME/s1600/sourceforge-driverupdate-ad.png" height="468" width="640" /></a></div>
<br />
It leads to a suspicious looking website, with Microsoft Partner logo and Windows logo, offering Windows driver updates. The kind my mother would click, thinking it's from Microsoft.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="http://1.bp.blogspot.com/-lXHh_2w-gg4/U3ajXwDk8PI/AAAAAAAAALc/cGDMZcELUrA/s1600/driverupdate-net.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="http://1.bp.blogspot.com/-lXHh_2w-gg4/U3ajXwDk8PI/AAAAAAAAALc/cGDMZcELUrA/s1600/driverupdate-net.png" height="472" width="640" /></a></div>
<br />
And here's the profile on web of trust: https://www.mywot.com/en/scorecard/driverupdate.net<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="http://1.bp.blogspot.com/-mWpwzGJbUCM/U3ah-hZhclI/AAAAAAAAALQ/RMpVEHD6p7Q/s1600/2014-05-17+01_39_14-driverupdate.net+_+WOT+Reputation+Scorecard+_+WOT+%2528Web+of+Trust%2529.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="http://1.bp.blogspot.com/-mWpwzGJbUCM/U3ah-hZhclI/AAAAAAAAALQ/RMpVEHD6p7Q/s1600/2014-05-17+01_39_14-driverupdate.net+_+WOT+Reputation+Scorecard+_+WOT+%2528Web+of+Trust%2529.png" height="529" width="640" /></a></div>
<br />
The site even manages to get a top rating on WoT by spamming good
ratings, even though all the important comments say it's a scam. WoT,
please fix.<br />
<blockquote class="tr_bq">
<span style="color: #444444;"><i>"they say I need over a dozen drivers updated. Confirming with the manufacturer, I am up to date. ..."</i></span> --pmheart6</blockquote>
<blockquote class="tr_bq">
<span style="color: #444444;"><i>"why do all the positive comments use poor english with typical chinese mistakes?? A dishonest sales trap. It's difficult to uninstall and must be done manually."</i></span> --KITRVL</blockquote>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="http://2.bp.blogspot.com/-69oM9xg9Xew/U3aiiim8FAI/AAAAAAAAALY/naFW3GKNfRk/s1600/2014-05-17+01_41_53-driverupdate.net+_+WOT+Reputation+Scorecard+_+WOT+%2528Web+of+Trust%2529.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="http://2.bp.blogspot.com/-69oM9xg9Xew/U3aiiim8FAI/AAAAAAAAALY/naFW3GKNfRk/s1600/2014-05-17+01_41_53-driverupdate.net+_+WOT+Reputation+Scorecard+_+WOT+%2528Web+of+Trust%2529.png" height="640" width="507" /></a></div>
<br />
<br />
SF changed ownership in 2012, and as the <a href="http://en.wikipedia.org/wiki/SourceForge" target="_blank">Wikipedia article</a> writes <i>"More recently additional revenue generation schemes, such as bundleware models have been trialled, with the goal of further improving sourceforge's revenue."</i><br />
<br />
This looks to me like beating a dead horse. There's only downhill from here. <br />
<br />
Please spare other people from such frustration. Even if the platform was good once, now is the time to move the code away. To <a href="https://bitbucket.org/" target="_blank">BitBucket</a> or <a href="https://code.google.com/" target="_blank">Google Code</a> or <a href="https://github.com/" target="_blank">GitHub</a> or wherever. Thanks.Anonymoushttp://www.blogger.com/profile/16815999018553645136noreply@blogger.com3tag:blogger.com,1999:blog-2415041862544909856.post-46316140831628808842014-04-29T04:52:00.000-07:002014-04-29T04:52:11.475-07:00Java: .equals() or == on enum values?<span style="font-size: large;">Both do pretty much the same thing: checking whether 2 enum values are the same. And if you search your code base, you probably find both kinds. There are some subtle differences. What are they - and which syntax should I use?</span><br />
<br />
<h3>
Same same - but different </h3>
Enum values are guaranteed singletons - and thus the == reference comparison is safe. The enum itself just delegates to Object.equals(), which does exactly that.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="http://4.bp.blogspot.com/-q1PQ8SJartI/U1-PuI2LWAI/AAAAAAAAAK0/0uArgOlx9i8/s1600/java-enum-equals-ok.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="http://4.bp.blogspot.com/-q1PQ8SJartI/U1-PuI2LWAI/AAAAAAAAAK0/0uArgOlx9i8/s1600/java-enum-equals-ok.png" /></a></div>
<br />
<br />
So if they execute the same code, why should I bother?<br />
<br />
<h3>
Learning the hard way - actual bug</h3>
I produced a bug which broke the build. Luckily we did have a unit test in place that caught it. But still I would have seen it earlier, had I used the "correct" syntax.<br />
<br />
So which one is it?<br />
<br />
<h3>
And the winner is: == </h3>
It provides <b>compile-time safety</b>. While <span style="color: #666666;"><span style="font-family: "Courier New",Courier,monospace;">MyColor.BLACK.equals(acceptsAnything)</span></span>gives a warning at most, the check <span style="color: #666666;"><span style="font-family: "Courier New",Courier,monospace;">MyColor.BLACK == something</span></span> won't even compile if <span style="color: #666666;"><span style="font-family: "Courier New",Courier,monospace;">something</span></span> is not an instance of <span style="font-family: "Courier New",Courier,monospace;"><span style="color: #666666;">MyColor</span></span>.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="http://2.bp.blogspot.com/-Am3QFWYQ2Hw/U1-QUdj7xiI/AAAAAAAAAK8/JVp3itiRtwk/s1600/java-enum-equals-error.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="http://2.bp.blogspot.com/-Am3QFWYQ2Hw/U1-QUdj7xiI/AAAAAAAAAK8/JVp3itiRtwk/s1600/java-enum-equals-error.png" /></a></div>
<br />
<br />
This makes it <b>refactoring-safe</b>. If you go - like me - and change the type of <span style="color: #666666;"><span style="font-family: "Courier New",Courier,monospace;">something </span></span>later on, you'll notice instantly.<br />
<br />
Another difference is the support for <span style="color: #666666;"><span style="font-family: "Courier New",Courier,monospace;">null</span></span>. The check with == allows <span style="color: #666666;"><span style="font-family: "Courier New",Courier,monospace;">null</span></span> on both sides. It doesn't throw, however, it may also "hide" a <span style="color: #666666;"><span style="font-family: "Courier New",Courier,monospace;">null</span></span> <span style="color: #666666;"><span style="font-family: "Courier New",Courier,monospace;"></span></span>value where there shouldn't be one.<br />
The check with equals() allows <span style="color: #666666;"><span style="font-family: "Courier New",Courier,monospace;">null</span></span> only on the right side, and throws a <span style="color: #666666;"><span style="font-family: "Courier New",Courier,monospace;">NullPointerException</span></span> if the left side is <span style="color: #666666;"><span style="font-family: "Courier New",Courier,monospace;">null</span></span>. That may be desired sometimes. Anyway, I vote for not letting <span style="color: #666666;"><span style="font-family: "Courier New",Courier,monospace;">null</span></span> slip into this comparison at all. It should be checked/handled before, instead of being <i>smart</i>. (See my <a href="http://www.flowstopper.org/2014/04/java-evolution-of-handling-null.html" target="_blank">article about null handling</a>.)<br />
So the comparison with == is <b>"safer" also at run-time</b> in that it never throws a NPE, but is possibly hiding a bug when the left side should never have been <span style="color: #666666;"><span style="font-family: "Courier New",Courier,monospace;">null</span></span>.<br />
<br />
Then there's the argument of <b>performance</b>. It's <b>irrelevant</b>. I'm not going there. <br />
<br />
And the <b>visual aspect</b>. Which one looks nicer?<br />
When I can have compile-time safety, I don't care about the looks. I was used to .equals() simply because that's how <span style="color: #666666;"><span style="font-family: "Courier New",Courier,monospace;">String</span></span>s are compared. But in retrospect that's a pretty lame explanation.<br />
On <a href="http://stackoverflow.com/questions/1750435/comparing-java-enum-members-or-equals" target="_blank">this StackOverflow question</a>, which is exactly about the topic, Kevin Bourrillion from Guava commented that <i>"== may appear incorrect to the reader until he looks at the types"</i> and concludes that <i>"In that sense, it's less distracting to read ".equals()"</i>. Au contraire! When I see <span style="color: #666666;"><span style="font-family: "Courier New",Courier,monospace;">CONSTANTS</span></span> around == I instantly know they're either enums, or primitives, of matching types. If not, the code is either red because it doesn't compile, or with a yellow warning from my intelligent IDE saying that .equals() should be used. For example <span style="font-family: "Courier New",Courier,monospace;"><span style="color: #666666;">String</span></span>s or primitive wrappers like <span style="font-family: "Courier New",Courier,monospace;"><span style="color: #666666;">Integer</span></span>. <br />
<br />
After that incident at the company we've decided to go with reference equality comparison ==.<br />
<br />Anonymoushttp://www.blogger.com/profile/16815999018553645136noreply@blogger.com4tag:blogger.com,1999:blog-2415041862544909856.post-66981730458950634372014-04-22T05:25:00.001-07:002014-04-22T09:00:00.985-07:00Java: Evolution of Handling Null References<span style="font-size: large;">Using null in programming is playing with fire. It's powerful and sometimes the right choice, but the infamous NullPointerException can sneak in quickly. That's why I advocate for every software project to include a section about handling null in the coding guidelines.</span><br />
<br />
The first time I've seen a Java exception was in the 90s in the web browser's status bar when surfing the net: a NPE caused by an applet. I had no idea what it meant and what I had done wrong. Today I know that the programmer let a null reference slip in where it wasn't expected to happen.<br />
<br />
When looking at open source software written in Java I often come across code where null references are used but not documented. Sometimes preconditions are in place. When stepping deeper it gets really tricky to figure out which variable is now allowed to be null and which is not. For the author it was obvious at the time of writing the code... but software becomes better when written and looked over by many, and thus it is important to make it clear for everyone, everywhere.<br />
<br />
Software is constantly shipped with NPEs detected later on. Redeployments and bugfix releases are expensive - and it's a pity because this kind of bug could be eliminated almost completely.<br />
<br />
<br />
Here's my personal evolution of dealing with null in Java.<br />
<br />
<h3>
Level 1: No Plan</h3>
Using it wherever, no information about it in the Javadoc.<br />
Fixing NPEs as they occur, seeing no problem in that.<br />
<blockquote class="tr_bq">
<pre>public class Foo {
public String getText() {
return null;
}
}</pre>
</blockquote>
<h3>
Level 2: Document Null - Sometimes</h3>
Realizing that NPEs are a problem that could and should be avoided. Detecting them late is expensive, especially after deployment.<br />
Starting to document variables, arguments and return values that can be null... incomplete.<br />
<blockquote class="tr_bq">
<pre>public class Foo {
/**
* @return the text, or null
*/
public String getText() {
return null;
}
}</pre>
</blockquote>
<h3>
Level 3: Add "Null" to Method Names</h3>
Realizing it's still a problem. Having Javadoc is nice, but useless when not read.<br />
Starting to name methods with null such as getFooOrNull() to force it to be seen.<br />
<blockquote class="tr_bq">
<pre>public class Foo {
/**
* @return the text, or null
*/
public String getTextOrNull() {
return null;
}
}</pre>
</blockquote>
<h3>
Level 4: Code Annotations</h3>
Using Jetbrains' null annotations: Annotating all variables with @Nullable and @NotNull. This is a huge step forward. The crippled method name pattern 'OrNull' is obsolete. The code is automatically documented. <br />
<blockquote class="tr_bq">
<pre>public class Foo {
@Nullable
public String getText() {
return null;
}
}</pre>
</blockquote>
And the best part: the IDE checks the code and warns on a mistake.<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="http://1.bp.blogspot.com/-tZAJ8KWXzok/U1Jg_1ZthhI/AAAAAAAAAKk/aIfgiW0dk3U/s1600/intellij-null-pointer-exception-warning.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="http://1.bp.blogspot.com/-tZAJ8KWXzok/U1Jg_1ZthhI/AAAAAAAAAKk/aIfgiW0dk3U/s1600/intellij-null-pointer-exception-warning.png" /></a></div>
<br />
<br />
Using these annotations strictly I don't remember causing a single NPE in years. The drawback is more typing, more text on the screen. But then we use static typing, and not defining null is just incomplete.
<br />
<br />
<h3>
Level 5: Guava's Optional </h3>
The concept: Instead of using the null reference directly, wrap it in another object that permits null. The getter methods on it myOptional.get(), myOptional.orNull() and myOptional.or(alternative) force the user to think about what to do when it's null. The API becomes extremely clean.<br />
<br />
If you don't know about it yet, read the Guava page about <a href="https://code.google.com/p/guava-libraries/wiki/UsingAndAvoidingNullExplained" target="_blank">using and avoiding null</a>.<br />
<br />
It took me a couple of days to get used to this. And I did produce a handful of bugs initially because I've used Optional.of() instead of Optional.fromNullable() by mistake.<br />
<br />
Although step 4 with annotations already got rid of NPEs and improved the code confidence, this was another big step forward. The API of the Optional class is clean, and the API of code using it is consistent and clear. A developer only has to learn the concept once, and because it's from Guava, sooner or later everyone will know it.<br />
<br />
The Guava team uses @Nullable annotations for the few places where null is permitted. Anywhere else there are no annotations.<br />
<br />
<h3>
Level 6: Java 8 has Optional built in</h3>
Oracle has a <a href="http://www.oracle.com/technetwork/articles/java/java8-optional-2175753.html" target="_blank">nice article</a> on it. The API is slightly different, and I have not made the transition to Java 8 yet.<br />
<br />
<br />
<br />
<h2>
Finger Pointing</h2>
The bugtracker for the <b>Glassfish </b>software currently has <b>1309 </b>matches for <b>NullPointerException</b>. <i>Wow</i>. <span style="color: #666666;">(Go to the <a href="https://java.net/jira/secure/QuickSearch.jspa" target="_blank">issue navigator</a>,
select the 11 projects on the left starting with "glassfish", and add
the query NullPointerException, hit enter. The software is
session-based, can't paste a link...)</span><br />
<br />
The <b>Grizzly </b>project has <b>69</b>. <br />
<br />
This
is a codebase that's still on level 1 regarding null. Exactly 2 years
ago I had recommended to improve the Javadoc and start using null
annotations. <a href="https://java.net/jira/browse/GRIZZLY-1259" target="_blank">The task</a> was accepted, got priority "Major" assigned, but is still open and things haven't changed.<br />
<br />
I had also mentioned in that task the undocumented method <span style="font-family: "Courier New",Courier,monospace;">int getQueueLimit()</span> which would return the magical <span style="font-family: "Courier New",Courier,monospace;">-1</span> for 'no limit'. Nowadays - being a level 5 guru ;-) - I'd instantly turn this into a self-documenting Optional. This forces users to think about the exceptional case. No horrible bugs from computations with -1 can occur. Users of it would then just do something like <span style="font-family: "Courier New",Courier,monospace;">getQueueLimit().or(Integer.MAX_INT)</span> or whatever suits their case - short, clear and safe.<br />
<br />
<br />
<br />
<h2>
My Recommendations</h2>
<h3>
1) Avoid Null when possible.</h3>
Consider the null object pattern.<br />
<br />
Return empty collections, not null. <br />
<br />
Throw UnsupportedOperationException() instead of returning null.<br />
Don't do this:
<br />
<blockquote class="tr_bq">
<pre>public Object foo() {
return null; //todo
}</pre>
</blockquote>
It is done sometimes as a quick way to satisfy the compiler. It's the no-impl
pattern. <br />
<br />
Do this instead:
<br />
<blockquote class="tr_bq">
<pre>public Object foo() {
throw new UnsupportedOperationException(); //todo
}</pre>
</blockquote>
If you return null then it (null) can go a long way until it throws a
nasty NullPointerException somewhere. By throwing UOE directly the
cause is clear in the stack trace.<br />
<br />
<h3>
2) Use Guava's Optional.</h3>
Wherever you would use null, use Optional. <br />
Except in very low level code.<br />
<br />
<h3>
3) Use Jetbrains's Null Annotations. </h3>
<br />
If
allowing null then use the @Nullable annotation.This is a must. It
automatically tells the user and the IDE that null is
possible/permitted.<br />
<br />
Use the @NotNull annotation everywhere else. This is optional. The Guava people do not, I do.<br />
<br />
To get the annotations using Maven:<br />
<br />
<dependency><br />
<groupId>com.intellij</groupId><br />
<artifactId>annotations</artifactId><br />
<version>12.0</version><br />
</dependency><br />
<br />
<br />Anonymoushttp://www.blogger.com/profile/16815999018553645136noreply@blogger.com4tag:blogger.com,1999:blog-2415041862544909856.post-36413592169464412452014-03-11T06:59:00.000-07:002014-03-11T06:59:12.840-07:00Software Versioning and BugfixesThere are <a href="http://en.wikipedia.org/wiki/Software_versioning" target="_blank">many ways</a> how to give version identifiers to software builds. <br />
<br />
The goals of software versioning, as I understand them:<br />
<ol>
<li>Give each build (release, snapshot) a <b>unique identifier</b>.</li>
<li><b>Apparent order</b>: it must be obvious which is newer when comparing 2.</li>
<li><b>Apparent changes</b>: contains breaking changes, new functionality, or just bug fixes.</li>
<li>Possibility to <b>release updates</b> later on that "fit in between".</li>
</ol>
I like the increasingly popular <a href="http://semver.org/" target="_blank">semantic versioning</a>. It accommodates all these goals.<br />
<br />
<h3>
Apparent Order</h3>
1.9.0 -> 1.10.0 -> 1.11.0<br />
This is important for me as a user, it lets me select the newest version quickly. <br />
<br />
<h3>
Apparent Changes</h3>
Going from 1.9.0 to 2.0.0 may mean that some of my use cases need to be adjusted, some things don't work the same anymore. I might prefer to stay on the "1" branch.<br />
<br />
Going from 1.9.0, 1.10.0 contains more functionality, it seems pretty safe. Experience taught me that new features bring new bugs - even if I don't make use of the new stuff.<br />
<br />
Going from 1.9.0 to 1.9.1 means there are just bug fixes. It is almost a safe bet to upgrade this. A quick look over the change-list helps me to decide where I might be affected. The risk is very low that this introduces new bugs.<br />
<br />
<h3>
Release Updates</h3>
When after 1.9 the version 1.10 has been released, and then bugs are found in 1.9.0 that should be fixed, not everyone will be happy with a 1.11 that now contains new functionality and bug fixes. Hence the 3 numbers.<br />
<br />
<h2>
H2 Database thinks otherwise</h2>
Unfortunately this software library that I use, like and value follows a different version system. Just like Google Chrome, they have been publishing new versions with what is effectively a single continuous version number.<br />
<br />
For a recent history see http://www.h2database.com/html/changelog.html<br />
And longer: http://mvnrepository.com/artifact/com.h2database/h2<br />
<br />
There are no bug fix releases. Each new version brings new features, improvements, bug fixes, and new bugs, which becomes clear when you follow the issues. But to learn in which version they were introduced, and so on, you need to dig and read the bug tracker.<br />
<br />
For a web browser, this release cycle OK. Give me the latest, I can cope with some level of annoyances and crashes now and then.<br />
<br />
The database however is the back bone of many applications. It is the piece of software that one relies on, that is the worst to break. And as such, I really wish it would maintain two code branches. One for latest developments, and one that lags behind where just fixes are applied.<br />
<br />
Whenever I consider updating this library in my code, I hesitate. Is it really necessary? Most times I answer no and move on. Updating means reading all recent changes, and running tests.<br />
<br />
I only use this database for read-only scenarios, not as a live database with active changes.<br />
<br />
<h3>
My suggestion to H2 and in general</h3>
<ol>
<li>Move code from Google Code to GitHub</li>
<li>Change to semantic versioning</li>
<li>Create a branch that lags behind, and let contributors do the work of maintaining it (applying just the fixes) </li>
</ol>
<br />
Anonymoushttp://www.blogger.com/profile/16815999018553645136noreply@blogger.com0tag:blogger.com,1999:blog-2415041862544909856.post-86580124387577861732013-12-02T08:45:00.000-08:002013-12-02T08:45:03.557-08:00IntelliJ IDEA: add Project Files to Version Control?<span style="font-size: large;">Do the contents of the <i>.idea</i> project folder and the <i>.iml</i> module files belong into version control?</span><br />
<br />
<b>Yes</b>, <a href="https://intellij-support.jetbrains.com/entries/23393067" target="_blank">says the IntelliJ team</a>:<br />
<blockquote class="tr_bq">
<span style="color: #666666;"><i>Here is what you need to share:</i></span><br />
<ul>
<li><span style="color: #666666;"><i><b>All </b>the <b>files under .idea</b> directory in the project root <b>except </b>the <b>workspace.xml</b> and <b>tasks.xml</b> files which store user specific settings</i></span></li>
<li><span style="color: #666666;"><i><b>All </b>the <b>.iml</b> module files that can be located in different module directories </i></span></li>
</ul>
</blockquote>
<br />
<b>No </b>for .iml files say <b>Maven </b>users who are annoyed by ever-changing iml files, see these 2 older but still open bugs:<br />
<ul>
<li><a href="http://youtrack.jetbrains.com/issue/IDEA-64312">http://youtrack.jetbrains.com/issue/IDEA-64312</a></li>
<li><a href="http://youtrack.jetbrains.com/issue/IDEA-79280">http://youtrack.jetbrains.com/issue/IDEA-79280</a></li>
</ul>
<br />
What are the drawbacks if I don't share these files? None, from my experience. When doing a fresh checkout of a project, IDEA asks whether I'd like to create a new project. Yes please, and all files are generated correctly. <br />
<br />
The only annoyance we have had at the company from time to time is when someone accidentally adds an .iml file to the VCS. There's a feature in IDEA to stop it from asking:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="http://3.bp.blogspot.com/-MYw7eHYPDCg/UpppIbLc8HI/AAAAAAAAAKE/uruJt0uYcFc/s1600/idea-vcs-ignoredfiles.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="http://3.bp.blogspot.com/-MYw7eHYPDCg/UpppIbLc8HI/AAAAAAAAAKE/uruJt0uYcFc/s1600/idea-vcs-ignoredfiles.png" height="419" width="640" /></a></div>
<div style="text-align: center;">
<span style="color: #666666;"><i>Settings -> Version Control -> Ignored Files</i></span></div>
<br />
This setting has to be applied in every project separately. And thus it's not very helpful in this case. Because every new project I check out, IDEA asks me whether I want to add the .iml file to version control (one by one), and I can just tell it to stop asking:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="http://4.bp.blogspot.com/-hJpdJ68y0Gs/UpqerUmOygI/AAAAAAAAAKU/wjA6QJpTHOE/s1600/idea-dont-ask-again.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="http://4.bp.blogspot.com/-hJpdJ68y0Gs/UpqerUmOygI/AAAAAAAAAKU/wjA6QJpTHOE/s1600/idea-dont-ask-again.png" /></a></div>
<br />
<h3>
Conclusion</h3>
For the time being we keep IDEA files out of the VCS. Our projects are usually multi-module maven, with lots of iml files. Your mileage may vary.<br />
<br />
<br />
<br />Anonymoushttp://www.blogger.com/profile/16815999018553645136noreply@blogger.com0tag:blogger.com,1999:blog-2415041862544909856.post-28181559414700757292013-11-29T03:00:00.000-08:002013-11-29T03:00:02.929-08:00Tabs and Saved Session Folders for PuTTYFor many years I've been using the <a href="http://en.wikipedia.org/wiki/PuTTY" target="_blank">PuTTY</a> network terminal to connect to remote servers when doing sysadmin tasks. And when I do, my <b>monitors quickly fill up</b> with those black windows. Remember web browsing before tabs? Like that. I totally lose track. <br />
<br />
The other thing that's annoying is that it does not let me <b>categorize my saved sessions</b>. All are in one alphabetical list. That might work when you just have a handful, but my list grew to dozens. Meh.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="http://4.bp.blogspot.com/-QeYY6BoTybo/Upe0d7sLO2I/AAAAAAAAAJo/m0iM5Ygd0bU/s1600/putty-saved-sessions.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="http://4.bp.blogspot.com/-QeYY6BoTybo/Upe0d7sLO2I/AAAAAAAAAJo/m0iM5Ygd0bU/s1600/putty-saved-sessions.png" height="320" width="317" /></a></div>
<br />
So I checked again today on the <a href="http://www.chiark.greenend.org.uk/~sgtatham/putty/" target="_blank">official site</a> for an update: <br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="http://3.bp.blogspot.com/-Wdp0NND9Ncs/UpeqedA3iSI/AAAAAAAAAJA/WII3lTLIhBU/s1600/official-putty-website.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="http://3.bp.blogspot.com/-Wdp0NND9Ncs/UpeqedA3iSI/AAAAAAAAAJA/WII3lTLIhBU/s1600/official-putty-website.png" height="310" width="400" /></a></div>
<br />
<br />
With such an user interface of the site, it would be too much to expect gimmicks in the program. Yes there was an update. Security fixes.<br />
<br />
So I googled for what else there is. And apparently there are plenty of wrappers around PuTTY that bring exactly what I want: Tabs and Session Folders. I don't know how they could hide from me for so long - maybe because neither the official site nor the Wikipedia page mention any.<br />
<br />
I've decided to go with this open source and actively maintained one: <a href="https://code.google.com/p/superputty/" target="_blank">superputty</a><br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="http://3.bp.blogspot.com/-K-147RyiHzY/Upe1rjOCwXI/AAAAAAAAAJ0/mmm_uddaljs/s1600/superputty2.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="http://3.bp.blogspot.com/-K-147RyiHzY/Upe1rjOCwXI/AAAAAAAAAJ0/mmm_uddaljs/s1600/superputty2.png" height="400" width="640" /></a></div>
<br />
<div class="separator" style="clear: both; text-align: center;">
</div>
<h3>
Conclusion</h3>
Same putty, more gui. Awesome. <br />
<br />
Anonymoushttp://www.blogger.com/profile/16815999018553645136noreply@blogger.com0tag:blogger.com,1999:blog-2415041862544909856.post-13239054947307989972013-11-08T05:43:00.000-08:002013-11-08T08:48:44.369-08:00Java: Should I assert or throw AssertionError?<a href="http://en.wikipedia.org/wiki/Assertion_%28software_development%29" target="_blank">Assertions</a> were introduced to the Java language in JDK 1.4, that was in 2002. It brought the <a href="http://docs.oracle.com/javase/7/docs/technotes/guides/language/assert.html" target="_blank">assert statement</a><br />
<blockquote class="tr_bq">
<b>assert </b>x != null : "x was null!";</blockquote>
and the throwable error class<br />
<blockquote class="tr_bq">
if (x==null) throw new <b>AssertionError</b>("x was null!");</blockquote>
Which one should I use in my code?<br />
<br />
<div>
<button onclick="alert('hrm, let`s see...')">1) assert</button>
<button onclick="alert('hrm, let`s see...')">2) AssertionError</button>
<button onclick="alert('smartass :p')">3) it depends</button>
</div>
<br />
<br />
<h2>
Well then, what's the difference?</h2>
<h3>
The assert statement</h3>
Unless assertions are actively turned on when running the program (-ea), they are not executed. They are still in the bytecode, but they don't run.<br />
<ul>
<li>Bugs go unnoticed. <br /><span style="color: #666666;">These bugs should have been detected already in unit tests and the testing phase before deployment when running with assertions on. But experience taught us that some slip through.</span></li>
<li>No performance loss. <br /><span style="color: #666666;">There are a few rare scenarios where it matters.</span></li>
<li>Side effects are possible.<br /><span style="color: #666666;">Badly programmed assertions can cause nasty side effects. Because sometimes the assert code is executed, and other times it's not, the program may behave slightly different.</span></li>
</ul>
Using the assert statement gives control to the runtime config whether they run or not. The choice is left to the person who runs the program. The choice can be made from run to run, no recompile is needed.<br />
<br />
<h3>
The AssertionError</h3>
The asserting code is always executed. Changing your mind about execution means a recompile and re-deployment.<br />
<ul>
<li>Bugs always show up.<br /><span style="color: #666666;">Even in production they abort the program.</span></li>
<li>Performance loss.<br /><span style="color: #666666;">In most cases it's irrelevant.</span></li>
<li>Guaranteed to have no side effects.<br /><span style="color: #666666;">The executed code is always the same.</span></li>
</ul>
<h3>
</h3>
<h2>
Vital or nice to have?</h2>
Programs were written in Java long before assertions were available. Some came up with their own self-made assertions logic - which was not as clean and short as the real thing. And most probably didn't.<br />
Assertions are not allowed to alter the program logic, were not always available, and are not mandatory. One can very well run the same program with them turned off. Conclusion: nice to have.<br />
<br />
However, it is not guaranteed that a specific bug ever shows up without assertions running. Let's take a flight simulator for example. Assume a computation bug that only occurs in a rarely executed code path. The bug can cause the airplane to fly at slightly reduced speed, and no one ever notices. Or it can be a number overflow, causing the plane to fly backwards. That will surely be seen each time.<br />
<br />
<h3>
Would assertions help in production code?</h3>
It depends on the domain. <b>Assertion means abort.</b> Is that what you'd want, to prevent the worst? Or would you rather try to go on, hoping that it's a minor, neglegtible bug?<br />
<ol>
<li>End-of-day accounting program: rather abort, alert the technicians, they fix it, and go on. No damage done, and bug fixed.</li>
<li>Real-time program where thousands of employees depend on it, and an abort means a big loss of work time. No abort. Hope that the bug eventually shows up as a side effect, and it can be traced and fixed.</li>
<li>Program where an abort is the worst case scenario, like a flight simulator: go on.</li>
</ol>
<br />
<h2>
Conclusions</h2>
<h3>
assert, not AssertionError</h3>
When writing library code, assert is the right choice. It gives the power to the user whether assertions should be on or off, whether he favors detection + abort, or to go unnoticed.<br />
<br />
When writing an application, use assert as well. If you want to enforce assertions, you can still hack in this piece of code, and if you change your mind later, you don't have to go through all assertions and replace them:<br />
<blockquote class="tr_bq">
<pre>static {
boolean assertsEnabled = false;
assert assertsEnabled = true; // <b>Intentional side effect</b>
if (!assertsEnabled)
throw new RuntimeException("Asserts must be enabled (-ea)!");
} </pre>
</blockquote>
Also, with assert, they can be <a href="http://docs.oracle.com/javase/7/docs/technotes/guides/language/assert.html#enable-disable" target="_blank">enabled on a per-package level</a><br />
<blockquote class="tr_bq">
<pre>java -ea:com.example... MyApp</pre>
</blockquote>
<br />
<h3>
AssertionError to satisfy compilation</h3>
Sometimes, when reaching code that should never be reached, an AssertionError is thrown to make the code compile. Example:<br />
<blockquote class="tr_bq">
<pre>switch (TrafficLight) {
case GREEN:
return doGreen();
case ORANGE:
return doOrange();
case RED:
return doRed();
default:
//Ugh! I gotta do something, but have no clue what to do!
//Let's abort the app and turn the semaphore offline.
throw new AssertionError("Dead code reached");
} </pre>
</blockquote>
An assert statement would not compile when a return is required.<br />
<br />
However, in some cases, it might be more suited to throw an exception instead of an error, for example an UnsupportedOperationException. In the above case an exception barrier could catch that, then turn all semaphores at the intersection to blinking orange for a minute, and then restart the green interval as it would from a clean program start and continue normal operation. That would have several advantages:<br />
<ul>
<li>be cheaper than sending a technician</li>
<li>the semaphore is off for short time only</li>
<li>while it's off it's blinking orange, rather than being totally off, that seems more secure</li>
</ul>
The problem would be detected in both cases. With an AssertionError it's in the output for free. And with UnsupportedOperationException it's the task of the one catching the exception to log it.<br />
<br />
So again, the choice is between a hard abort, or giving the program the chance to recover and continue if a higher level decides to do so.<br />
<br />
<br />
<h3>
What I'm missing: detection and logging! </h3>
In the production scenarios 2 and 3 from above I'd want a 3rd way of handling assertions, which is not offered by Java's assertion feature.<br />
<br />
Java has 2 strategies:<br />
<ol>
<li>Don't even check, hence no abort</li>
<li>Check, and conditionally abort or continue</li>
</ol>
And I'm missing the 3rd one with the behavior:<br />
<ol start="3">
<li>Run assertion code to detect bugs and don't abort, but instead log.<br /><span style="color: #666666;">It's
a clear bug, it's detected, so log it. There's no cheaper way to detect
it than right here, in the assert code that was written already.</span></li>
</ol>
<span style="color: #666666;"> </span><br />
<ol start="3">
</ol>
<h3>
Configure your IDE to run with assertions</h3>
It strikes me that the default runconfig in the most common IDEs does not have assertions enabled. It actually happened to me that I had spent way too much time chasing a bug, when the assertion would have shown it instantly - but they weren't on.<br />
<br />
In IntelliJ IDEA: You need to modify the Defaults for all kinds that you're using: Application, JUnit, TestNG, ... and changing the defaults does not change the runconfigs you've created earlier. And you need to do this in every project, separately. (Please add a comment if you know how to set this once and for all!)<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="http://3.bp.blogspot.com/-5rIfML-aRJk/UnzcC3FPyVI/AAAAAAAAAIw/uT2O-zvk-O8/s1600/intellij-enable-assertions.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="http://3.bp.blogspot.com/-5rIfML-aRJk/UnzcC3FPyVI/AAAAAAAAAIw/uT2O-zvk-O8/s1600/intellij-enable-assertions.png" /></a></div>
<br />
For Eclipse there's an explanation here <a href="http://stackoverflow.com/questions/5509082/eclipse-enable-assertions">http://stackoverflow.com/questions/5509082/eclipse-enable-assertions</a> also see the 2nd answer about JUnit tests.<br />
<br />Anonymoushttp://www.blogger.com/profile/16815999018553645136noreply@blogger.com0tag:blogger.com,1999:blog-2415041862544909856.post-54482255296618223242013-11-04T03:00:00.000-08:002013-11-04T23:04:21.064-08:00Java toString(): the Program Logic vs. Debug Dilemma<span style="font-size: large;">I'll start with my real world problem of how to implement toString() for my new class, followed by an analysis of how Java uses toString(), and finishing with my conclusions.</span><br />
<br />
<br />
<h3>
Real world problem: my class</h3>
Here's the (stripped down for simplicity) version of my new class:<br />
<br />
<pre style="background: #f0f0f0; border: 1px dashed #CCCCCC; color: black; font-family: arial; font-size: 12px; height: auto; line-height: 20px; overflow: auto; padding: 0px; text-align: left; width: 99%;"><code style="color: black; word-wrap: normal;">1: /**
2: * Represents a possibly multi-byte character and provides information about it.
3: * <p>A UnicodeCharacter is the equivalent of a Java "code point".</p>
4: */
5: public final class UnicodeCharacter {
6: private final int codepoint;
7: public UnicodeCharacter(int codepoint) {
8: this.codepoint = codepoint;
9: }
10: public int getCodepoint() {
11: return codepoint;
12: }
13: /**
14: * @return Array with usually 1 character, 2 characters for multi-byte.
15: */
16: public char[] getChars() {
17: return UCharacter.toChars(codepoint);
18: }
19: /**
20: * @return Tells if the {@link #getCodepoint codepoint} is for a surrogate pair.
21: */
22: public boolean isMultiByte() {
23: return getChars().length>1;
24: }
25: /**
26: * @return For example the category UCharacterCategory.UPPERCASE_LETTER
27: */
28: public Byte getCategory() {
29: return (byte) UCharacter.getType(codepoint);
30: }
31: /**
32: * See {UCharacter#getName}
33: */
34: public String getName() {
35: return UCharacter.getName(codepoint);
36: }
37: }
</code></pre>
<br />
<br />
Now for toString(), what should it be?<br />
<br />
<h4>
Suggestion 1: for the human user, debug output</h4>
<pre style="background: #f0f0f0; border: 1px dashed #CCCCCC; color: black; font-family: arial; font-size: 12px; height: auto; line-height: 20px; overflow: auto; padding: 0px; text-align: left; width: 99%;"><code style="color: black; word-wrap: normal;">1: public String toString() {
2: return "UnicodeCharacter{" +
3: "cp=" + codepoint +
4: " ,string='" + getString() +
5: " ,name=" + getName() +
6: '}';
7: }
</code></pre>
Example output:<br />
<ul>
<li>UnicodeCharacter{cp=65,string='A',name=LATIN CAPITAL LETTER A}</li>
<li>UnicodeCharacter{cp=1040,string='А',name=CYRILLIC CAPITAL LETTER A}</li>
<li>UnicodeCharacter{cp=32,string=' ',name=SPACE} </li>
</ul>
<br />
<ul>
</ul>
<h4>
Suggestion 2: for the machine, program logic, concatenateable</h4>
<pre style="background: #f0f0f0; border: 1px dashed #CCCCCC; color: black; font-family: arial; font-size: 12px; height: auto; line-height: 20px; overflow: auto; padding: 0px; text-align: left; width: 99%;"><code style="color: black; word-wrap: normal;">1: public String toString() {
2: return UTF16.valueOf(codepoint);
3: }
</code></pre>
<br />
Example output for the same 3 (yes 3) characters:<br />
<ul>
<li>A</li>
<li>А</li>
<li> </li>
</ul>
<br />
Both have their advantages and drawbacks. It certainly needs a concatenateable method, but that can be named "getString()". The debug method is nice to have - you see, just by looking at the characters you can't tell whether it's the Latin or Cyrillic A, or what kind of whitespace it is.<br />
<br />
Unfortunately, in this case, expanding the object in the debugger doesn't help, because solely the code point is a property of the object. The other information (character and name) are computed:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="http://3.bp.blogspot.com/-SWm5QjGQ_gw/UnaO8wfsaKI/AAAAAAAAAIg/SH_CvT_HbNY/s1600/java-debugger-tostring.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="http://3.bp.blogspot.com/-SWm5QjGQ_gw/UnaO8wfsaKI/AAAAAAAAAIg/SH_CvT_HbNY/s1600/java-debugger-tostring.png" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="http://3.bp.blogspot.com/-Q2B2LE_qcrM/UnaOrzcw26I/AAAAAAAAAIY/iiTNoaoC9Bk/s1600/java-debugger-tostring.gif" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><br /></a></div>
<br />
<br />
<h3>
Analysis of Java's toString() </h3>
Here's what Java has to say about <a href="http://docs.oracle.com/javase/7/docs/api/java/lang/Object.html#toString%28%29" target="_blank">Object.toString()</a>:<br />
<blockquote class="tr_bq">
<div class="block">
<i>Returns a string representation of the object. In general, the
<code>toString</code> method returns a string that
"textually represents" this object. The result should
be a concise but informative representation that is easy for a
person to read.</i></div>
</blockquote>
Both my suggestions follow the specification. The one with debug info is easier to read for a person. But I'm not sold yet.<br />
<br />
<h4>
Who calls toString()?</h4>
<ul>
<li>Java itself:<br />When doing string concatenation: String s = myString + myCar;<br />Is the same as doing String s = myString<span style="color: #666666;">.toString()</span>.concat(myCar.toString());</li>
<li>JDK methods:<br />String.valueOf(Object obj), and thus every method that uses this such as PrintStream.print(Object o).<br />Arrays.toString(Object[] a) for every object in the array a.<br />StringBuilder and StringBuffer: the toString() method is used as the build method.</li>
<li>Logging:<br />System.out.println().<br />Your favorite logging framework.</li>
<li>Debugging:<br />Your favorite IDE in the debugger.</li>
</ul>
<br />
Hrm. So there are mainly 2 uses:<br />
<ol>
<li>String representation: toString() returns the object's value "as string" as close as possible.<br />It is absolutely required to override toString(), and to do it in this way.</li>
<li>Debug information: the object's values for the human.<br />For example IntelliJ IDEA's default toString() template generates this kind.<br />It's just nice to have.</li>
</ol>
Sometimes, as an additional benefit, the object provides a constructor accepting that string as a parameter to re-create it. Example: <a href="http://docs.oracle.com/javase/7/docs/api/java/lang/Integer.html#toString%28%29" target="_blank">Integer.toString()</a> and <a href="http://docs.oracle.com/javase/7/docs/api/java/lang/Integer.html#Integer%28java.lang.String%29" target="_blank">new Integer(String)</a>.<br />
<br />
<h4>
How does Java in the JDK define toString() in their classes?</h4>
For some simple value classes there's not much choice. Integer for example: returning "-43" makes sense.<br />
<br />
<a href="http://docs.oracle.com/javase/7/docs/api/java/lang/Character.html#toString%28%29" target="_blank">Character</a> could return more than just the character as string, but it does not. <a href="http://docs.oracle.com/javase/7/docs/api/java/lang/String.html#toString%28%29" target="_blank">String</a> could tell the length and cut it if it's too much, but it does not. <a href="http://docs.oracle.com/javase/7/docs/api/java/lang/StringBuilder.html#toString%28%29" target="_blank">StringBuilder</a> and <a href="http://docs.oracle.com/javase/7/docs/api/java/lang/StringBuffer.html#toString%28%29" target="_blank">StringBuffer</a> could report the appended chunks separately, and tell how many, and cut, but they don't. If they would, the classes would need a separate method for string concatenation, and concatenation with + would not work anymore. Now here's an observation: They all implement <a href="http://docs.oracle.com/javase/7/docs/api/java/lang/CharSequence.html" target="_blank">CharSequence</a>, which was added in JDK 1.4, and it overrides the toString() method signature just to say something about it:<br />
<blockquote class="tr_bq">
<i>Returns a string containing the characters in this sequence in the same order as this sequence. The length of the string will be the length of this sequence. </i></blockquote>
So that's why.<br />
<br />
<h3>
Conclusions</h3>
My class UnicodeCharacter is a wrapper around a unicode codepoint just like Character is a wrapper around the char primitive. It's a character supporting those that don't fit into a char. And as such it really should implement the CharSequence interface. Then the decision is made: toString() must be suggestion 2, only returning the character's string value.<br />
<br />
In some rare cases it would be nice to have 2 different methods: one for the string value (toString()) and one for the debug info (toDebug() or toDebugString()). The method could be defined in Object, with a default implementation: calling toString().<br />
<br />
<br />Anonymoushttp://www.blogger.com/profile/16815999018553645136noreply@blogger.com3tag:blogger.com,1999:blog-2415041862544909856.post-6189239336800291882013-10-30T05:00:00.000-07:002013-10-30T05:00:06.541-07:00Password-protect Play2 Framework WebappThere are numerous extensions to bring authentication and access control to your <a href="http://www.playframework.com/" target="_blank">Play</a> based website. For example the <a href="https://github.com/schaloner/deadbolt-2" target="_blank">Deadbolt 2 authorization system</a> lets you define access rights per controller and method. Or you can roll your own, as this <a href="http://www.playframework.com/documentation/2.2.0/JavaGuide4" target="_blank">step by step guide</a> shows.<br />
<br />
What to do if you just want <a href="http://en.wikipedia.org/wiki/Basic_access_authentication" target="_blank">basic http authentication</a> for the whole site? As of today there's no such thing built in. (If this changes, let me know...)<br />
<br />
If you're serving your Play pages through Apache as reverse proxy, you're lucky.<br />
<br />
Going through a reverse proxy is a good idea anyway:<br />
<ul>
<li>You get the option for load balancing and failover: run multiple instances.</li>
<li> Run multiple Play sites on the same machine, on whatever port number, and expose them all on port 80 to the outside.</li>
</ul>
Your apache website definition looks simething like this:<br />
<pre style="-webkit-text-stroke-width: 0px; background-color: #fafafa; border: 1px solid rgb(218, 218, 218); color: #484848; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; margin: 1em 1em 1em 1.6em; orphans: auto; overflow-x: auto; overflow-y: hidden; padding: 2px 2px 2px 0px; text-align: start; text-indent: 0px; text-transform: none; widows: auto; width: auto; word-spacing: 0px;"><VirtualHost *:80>
ServerName my-play-app.example.com
ProxyPreserveHost on
<Location />
ProxyPass http://192.168.56.100:9000/ connectiontimeout=9999999 timeout=9999999
ProxyPassReverse http://192.168.56.100:9000/
AuthType Basic
AuthName "whatever"
AuthUserFile /etc/apache2/sites-available/.htpasswd-mysite
Require valid-user
</Location>
</VirtualHost></pre>
I'm running my Play app in a virtual machine (192.168.56.100) on standard port 9000. The connection timeout is there so that long running tasks are not aborted by the proxy.<br />
<br />
Create the password file as usual:<br />
<span style="font-family: "Courier New",Courier,monospace;">cd /etc/apache2/sites-available/</span><br />
<span style="font-family: "Courier New",Courier,monospace;">htpasswd -c .htpasswd-mysite newuser</span><br />
<br />
And then refresh Apache, and you're done:<br />
<span style="font-family: "Courier New",Courier,monospace;"></span><span style="font-family: "Courier New",Courier,monospace;">service apache2 reload</span><br />
<br />
<br />Anonymoushttp://www.blogger.com/profile/16815999018553645136noreply@blogger.com0tag:blogger.com,1999:blog-2415041862544909856.post-46290416406323129712013-10-09T07:10:00.000-07:002013-10-09T07:21:02.214-07:00IntelliJ IDEA stopped working after Windows 7 Updates<span style="font-size: large;"><i>(This post is only of interest to people having the same situation, probably finding this through Google search.)</i></span><br />
<br />
<h3>
Problem</h3>
After finishing the last batch of <b>Windows 7 updates</b> with some issues (blue screen), my computer was fine, all programs worked normally... except for one: <b>IntelliJ IDEA just wouldn't start</b>. I was running version 12.1.3, and upgrading to 12.1.6 would not fix it. Also, the earlier and still installed versions 11 would not work.<br />
<br />
The process started normally, as seen here, but the application was missing:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="http://3.bp.blogspot.com/-9lUZP4g4KMQ/UlVhykv9HaI/AAAAAAAAAH8/pW3lvrYVHaE/s1600/windows-task-manager.gif" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="http://3.bp.blogspot.com/-9lUZP4g4KMQ/UlVhykv9HaI/AAAAAAAAAH8/pW3lvrYVHaE/s1600/windows-task-manager.gif" height="295" width="400" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
</div>
<br />
The Windows event viewer had no message about it.<br />
<br />
There was a thread dump in the IntelliJ IDEA log folder <i>c:\users\my-username\.IntelliJIdea12\system\log\threadDumps-timestamp\...txt</i> with a time of the program start, but the text within the file was not helpful to me.<br />
<br />
<h3>
<b>Solution </b></h3>
What solves the problem is to right-click the program in the Windows start menu, and select <b>"Run as administrator"</b>. <br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="http://1.bp.blogspot.com/--vWvxExgpIc/UlViuLHIaZI/AAAAAAAAAII/VI53HxnSyWs/s1600/startmenu-run-as-administrator.gif" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="http://1.bp.blogspot.com/--vWvxExgpIc/UlViuLHIaZI/AAAAAAAAAII/VI53HxnSyWs/s1600/startmenu-run-as-administrator.gif" height="400" width="236" /></a></div>
<br />
<br />
Thanks to my wife for figuring it out.<br />
<br />Anonymoushttp://www.blogger.com/profile/16815999018553645136noreply@blogger.com0tag:blogger.com,1999:blog-2415041862544909856.post-15291137032297094722013-06-17T05:32:00.000-07:002013-06-17T05:32:37.875-07:00Multiple simultaneous browser sessionsI need multiple simultaneous, persistent browsing sessions:<br />
<ul>
<li>as a developer I frequently need multiple logins to test things</li>
<li>as a person concerned about my privacy I use multiple public profiles, multiple email addresses</li>
<li>sometimes I use a proxy server to watch ip-restricted tv from another country </li>
</ul>
<br />
<b>Simultaneous</b>: I don't want to log in and out of accounts all the time.<br />
<b>Persistent</b>: It's nice when my computer remembers logins, preferences, proxies, bookmarks, cookies and all.<br />
<br />
My primary browser is Chrome. It's fast and stable and has all I need for most tasks. But it only lets me use one session at a time (besides the temporary inkognito ones). Some Google products such as Gmail <a href="https://support.google.com/accounts/answer/1721977?hl=en" target="_blank">allow multi-signin</a> but as the page says at the end, some products don't. These include Google groups and Blogger. And I need them (this is a Blogger blog). But Google wouldn't be Google if it wouldn't offer solutions to the problem:<br />
<ol>
<li>sign out, and in with other account</li>
<li>sign in with another browser</li>
</ol>
So another browser it is. <br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="http://3.bp.blogspot.com/-x1TtuBjIuGU/Ub4WRLTitkI/AAAAAAAAAHE/sj0o834oHQI/s1600/scumbag-opera.gif" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"><img border="0" src="http://3.bp.blogspot.com/-x1TtuBjIuGU/Ub4WRLTitkI/AAAAAAAAAHE/sj0o834oHQI/s1600/scumbag-opera.gif" /></a></div>
I've tried using Opera for one of my accounts. But it's no pleasure. Gmail in Opera sucks. Google groups in Opera suck. And Blogger to write text is horrible (it's bad enough in Chrome already). One week ago I had 5 tabs open in Opera and it consumed 1.8GB ram. No thank you.<br />
<br />
Anyway, I might want more sessions than there are acceptable browsers. <br />
<br />
<h3>
Firefox to the rescue</h3>
Our relationship has become a bit rusty over the years, but I still remember the good times we've shared. It feels sluggish like a heavy KV-1 tank compared to a light Luchs in World of Tanks terms. But one great feature it has is that it not only allows multiple profiles (<a href="https://support.google.com/chrome/answer/2364824" target="_blank">as does Chrome</a>), but also to run them simultaneously. The trick is to not only make it ask for the profile at the first start, but at every start. And here it is:<br />
<br />
1) Click the start button, right-click the Firefox program, select "Properties"<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
</div>
<div class="separator" style="clear: both; text-align: center;">
</div>
<div class="separator" style="clear: both; text-align: center;">
</div>
<div class="separator" style="clear: both; text-align: center;">
</div>
<div class="separator" style="clear: both; text-align: center;">
<a href="http://3.bp.blogspot.com/-3DigvTvgp8s/Ub3eQiIgsBI/AAAAAAAAAGs/62aWD7-JXd8/s1600/windows-startmenu.gif" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="http://3.bp.blogspot.com/-3DigvTvgp8s/Ub3eQiIgsBI/AAAAAAAAAGs/62aWD7-JXd8/s1600/windows-startmenu.gif" height="307" width="320" /></a></div>
2) At the end of the "Target" command append <b>-P -no-remote</b><br />
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="http://4.bp.blogspot.com/-pv8JmS3pcCs/Ub3eQPLGAnI/AAAAAAAAAGk/jVr7pTqirhs/s1600/firefox-run-properties.gif" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="http://4.bp.blogspot.com/-pv8JmS3pcCs/Ub3eQPLGAnI/AAAAAAAAAGk/jVr7pTqirhs/s1600/firefox-run-properties.gif" height="320" width="226" /> </a></div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<div class="separator" style="clear: both; text-align: left;">
3) Provide administrator permission if asked </div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
</div>
<div class="separator" style="clear: both; text-align: center;">
</div>
<div class="separator" style="clear: both; text-align: center;">
</div>
<div class="separator" style="clear: both; text-align: center;">
</div>
<div class="separator" style="clear: both; text-align: center;">
</div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://4.bp.blogspot.com/-mG4nGvMjjwg/Ub3eQG8yPdI/AAAAAAAAAGg/dA5gIZseUag/s1600/windows-administrator-permissions.gif" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="http://4.bp.blogspot.com/-mG4nGvMjjwg/Ub3eQG8yPdI/AAAAAAAAAGg/dA5gIZseUag/s1600/windows-administrator-permissions.gif" height="153" width="320" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
</div>
<div class="separator" style="clear: both; text-align: center;">
</div>
<br />
4) From now on each time you start Firefox it will ask which profile to use by showing the profile manager. And each window opened this way will run its own, isolated session (and system process).<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://2.bp.blogspot.com/-eEkZQLDv6Z4/Ub3eQNS4mUI/AAAAAAAAAGc/OAe0h3FC7D4/s1600/firefox-profilemanager.gif" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="http://2.bp.blogspot.com/-eEkZQLDv6Z4/Ub3eQNS4mUI/AAAAAAAAAGc/OAe0h3FC7D4/s1600/firefox-profilemanager.gif" height="247" width="320" /></a></div>
<br />
The basic knowledge for this magic can be found here <a href="http://kb.mozillazine.org/Profile_manager">http://kb.mozillazine.org/Profile_manager</a> but the real trick is documented here <a href="http://kb.mozillazine.org/Opening_a_new_instance_of_your_Mozilla_application_with_another_profile">http://kb.mozillazine.org/Opening_a_new_instance_of_your_Mozilla_application_with_another_profile</a><br />
<br />
<br />
<br />
<!-- Blogger automated replacement: "https://images-blogger-opensocial.googleusercontent.com/gadgets/proxy?url=http%3A%2F%2F4.bp.blogspot.com%2F-mG4nGvMjjwg%2FUb3eQG8yPdI%2FAAAAAAAAAGg%2FdA5gIZseUag%2Fs1600%2Fwindows-administrator-permissions.gif&container=blogger&gadget=a&rewriteMime=image%2F*" with "https://4.bp.blogspot.com/-mG4nGvMjjwg/Ub3eQG8yPdI/AAAAAAAAAGg/dA5gIZseUag/s1600/windows-administrator-permissions.gif" --><!-- Blogger automated replacement: "https://images-blogger-opensocial.googleusercontent.com/gadgets/proxy?url=http%3A%2F%2F2.bp.blogspot.com%2F-eEkZQLDv6Z4%2FUb3eQNS4mUI%2FAAAAAAAAAGc%2FOAe0h3FC7D4%2Fs1600%2Ffirefox-profilemanager.gif&container=blogger&gadget=a&rewriteMime=image%2F*" with "https://2.bp.blogspot.com/-eEkZQLDv6Z4/Ub3eQNS4mUI/AAAAAAAAAGc/OAe0h3FC7D4/s1600/firefox-profilemanager.gif" -->Anonymoushttp://www.blogger.com/profile/16815999018553645136noreply@blogger.com2tag:blogger.com,1999:blog-2415041862544909856.post-81310537074988673982013-04-10T07:36:00.000-07:002013-04-19T07:16:55.387-07:00ExtJS debug version: there it is - but useless<span style="font-size: large;">This is a follow-up post to my last week's "</span><a href="http://www.flowstopper.org/2013/04/extjs-desperately-need-debug-version.html" target="_blank"><span style="font-size: large;">ExtJS: desperately need a debug version</span></a><span style="font-size: large;">".</span><br />
<span style="font-size: large;">A user comment pointed me to the "-dev" version. Apparently there is such a file now containing some lines of error checking (not too many):</span><br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="http://1.bp.blogspot.com/-lRlusnI-WT8/UWVpQcBC1dI/AAAAAAAAAFI/d_JS4pWjt-w/s1600/extjs4-dev-diff.gif" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="http://1.bp.blogspot.com/-lRlusnI-WT8/UWVpQcBC1dI/AAAAAAAAAFI/d_JS4pWjt-w/s1600/extjs4-dev-diff.gif" height="384" width="640" /></a></div>
See
<a href="http://www.diffnow.com/?report=ahx86">http://www.diffnow.com/?report=ahx86</a> for the diff. I compared <a href="http://cdn.sencha.io/ext-4.2.0-gpl/ext-debug.js">http://cdn.sencha.io/ext-4.2.0-gpl/ext-debug.js</a> with <a href="http://cdn.sencha.io/ext-4.2.0-gpl/ext-dev.js">http://cdn.sencha.io/ext-4.2.0-gpl/ext-dev.js</a> <span style="color: #666666;">(My Chrome browser crashed a couple of times with these large files at DiffNow and similar online diff tools.)</span><br />
<br />
A download of the latest version 4.2 contains, among many other files:<br />
<br />
ext-all.js 1'402 KB
<br />
ext-all-debug.js 3'262 KB<br />
ext-all-debug-w-comments.js 6'052 KB<br />
ext-all-dev.js 6'109 KB<br />
<br />
So what Sencha needs to do now is to update this page <a href="http://www.sencha.com/learn/debugging-ext-js-applications" target="_blank">http://www.sencha.com/learn/debugging-ext-js-applications</a> and recommend to include ext-all-dev.js instead of ext-all-debug.js, while keeping ext-all.js for production.<br />
<br />
<h3>
And, does it help?</h3>
A couple days forward and I upgraded my app (still in development) from ExtJS 4.1 to 4.2. All seemed fine. There were <a href="http://docs.sencha.com/ext-js/4-2/#!/guide/upgrade_42" target="_blank">not too many backward-incompatible changes</a> this time. Plus, I have the dev version now which would alert me of problems right?<br />
<br />
A screen using 4.1:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="http://1.bp.blogspot.com/-vco1C01ferI/UWbn0qbxvOI/AAAAAAAAAFY/34sIV5vRkgk/s1600/extjs-4.1-searchfield.gif" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="http://1.bp.blogspot.com/-vco1C01ferI/UWbn0qbxvOI/AAAAAAAAAFY/34sIV5vRkgk/s1600/extjs-4.1-searchfield.gif" height="492" width="640" /></a></div>
The same screen with 4.2:<br />
<link rel="stylesheet" href="http://cdn.sencha.io/ext-4.2.0-gpl/resources/css/ext-all-gray.css"/><br />
<script src="http://cdn.sencha.io/ext-4.2.0-gpl/ext-all-dev.js"></script><br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="http://3.bp.blogspot.com/-eZmwslpcX_4/UWboJsMsuHI/AAAAAAAAAFg/SME6Qodu5ME/s1600/extjs-4.2-searchfield.gif" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="http://3.bp.blogspot.com/-eZmwslpcX_4/UWboJsMsuHI/AAAAAAAAAFg/SME6Qodu5ME/s1600/extjs-4.2-searchfield.gif" height="492" width="640" /></a></div>
<br />
The search field on the toolbar is missing. Just gone. Nothing in the console. The grid search extension is from <a href="https://gist.github.com/aghuddleston/3297619/raw/fa5baf4c39387ec53662115be6acf80f20c37a6f/Searching.js" target="_blank">here</a> but that is irrelevant.<br />
<br />
Another week passed by, and another case cost me 15 minutes of searching: I've created a new form panel with just one field, copy-pasted from an official example.<br />
<br />
{<br /> fieldLabel: 'My field',<br /> name: 'myField',<br /> allowBlank: false<br />}<br />
<br />
Loading it in the browser, but the panel remains empty (except for the button bar). No error or warning output of course. What's wrong? Something with the panel dimensions? The panel has no width or height?
(ExtJS developers will know...)
Trying all kinds of combinations. Turns out the problem is very, very basic. I forgot to specify what kind of field it is (xtype: 'textfield'). The example had it configured in the parent object as 'defaultType', and I did not copy that. So ext was supposed to render an element to the screen, but it was not informed about what kind of element it is. What does it do? Apparently nothing... How about at least logging a warning?<br />
<br />
<h3>
Conclusion</h3>
Nothing has changed for me. Making mistakes or upgrading ExJS means digging.Anonymoushttp://www.blogger.com/profile/16815999018553645136noreply@blogger.com3tag:blogger.com,1999:blog-2415041862544909856.post-13827344895293858452013-04-04T22:01:00.001-07:002013-04-10T09:59:03.494-07:00ExtJS: desperately need a debug version<div style="text-align: center;">
<span style="font-size: large;"><span style="background-color: #f1c232;">Update to this post: </span><a href="http://www.flowstopper.org/2013/04/extjs-debug-version-there-it-is.html" target="_blank"><span style="background-color: #f1c232;">there is a debug version</span></a><span style="background-color: #f1c232;">.</span></span></div>
<div style="text-align: center;">
<span style="background-color: #f1c232;"><br /></span></div>
<span style="font-size: large;">I missed it when using ExtJS 2, then with ExtJS 3. Now I'm using ExtJS 4 for a new web user interface, and the situation is the same: I desperately need a debug version of ExtJS!</span><br />
<br />
<h3>
On the plus side: The best web gui toolkit</h3>
ExtJS is, in my opinion, the most complete JavaScript library for making desktop-like apps in the browser. It has been there for long time, and is actively developed. It's relatively easy to extend components and develop your own. The community is large, the documentation is OK, and it's possible to create useful, functional, "rich" user interfaces. It's possible to get the job done.<br />
<br />
<h3>
Beware: It's a full time job</h3>
The <a href="http://dev.sencha.com/deploy/ext-4.0.0/examples/" target="_blank">examples</a> look nice, and one could get the idea that it's a quick and easy path to develop your own rich gui. Nah. It's all trial and error F5 style development. It takes a lot of time and effort to get halfway fluent with it. There are many gotchas to learn about.<br />
<br />
<h3>
It sucks the energy out of me</h3>
For me, working with ExtJS is no pleasure. It brings a new flow stopper way too often. Why?<br />
<div>
<ol>
<li><b>The nature of JavaScript.</b><br />JavaScript is not a type safe language. There's no safe refactoring. No compile time confidence. That's a fact, nothing to improve here.</li>
<li><b>ExtJS performs no checks.</b><br />No input checking (preconditions, assertions), no checks for common errors.</li>
</ol>
Let's look at an example:
"Uncaught TypeError: Object #<object> has no method 'read'"</object>
<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="http://1.bp.blogspot.com/-fUiHhpF2sXY/UVcUwYEqr4I/AAAAAAAAAEo/4ioGGce3Uwk/s1600/extjs-debug-1.gif" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="http://1.bp.blogspot.com/-fUiHhpF2sXY/UVcUwYEqr4I/AAAAAAAAAEo/4ioGGce3Uwk/s1600/extjs-debug-1.gif" /></a></div>
<br />
Aha, some script execution error occurred. Let's check the detail:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="http://1.bp.blogspot.com/-haoV5ao8rO4/UVcVMDZAXQI/AAAAAAAAAEw/j9YsGgxgv1M/s1600/extjs-debug-2.gif" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="http://1.bp.blogspot.com/-haoV5ao8rO4/UVcVMDZAXQI/AAAAAAAAAEw/j9YsGgxgv1M/s1600/extjs-debug-2.gif" /></a></div>
<br />
Not that helpful. Something internal in ExtJS on line 39145 failed. ExtJS does not catch this one (or any other) and tell me what the real problem is. Nor does the stack trace go back to my userland code.<br />
<br />
In this case the <a href="http://stackoverflow.com/questions/12058947/extjs-uncaught-typeerror-object-object-has-no-method-read" target="_blank">problem</a> was that I did not include some data store model prior to using it. My fault. But it doesn't have to be. There are plenty of reasons for such time consuming debugging, just because problems are never detected, and throw at last moment, deep down:<br />
<div>
<ul>
<li>Developer error: wrong API use</li>
<li>ExtJS bug</li>
<li>
ExtJS
annoyance</li>
<li>Old code: upgrading an older app, or copying an older example from the internet</li>
</ul>
<br />
<ul>
</ul>
</div>
</div>
<h3>
But wait: I'm using "ext-all-debug.js"</h3>
<div>
Unfortunately, the naming of the ExtJS JavaScript files is, imo, wrong.<br />
<br />
<a href="http://jquery.com/download/" target="_blank">JQuery</a> got it right:<br />
The original JS file, with apidoc: http://code.jquery.com/jquery-1.9.1.js<br />
The minified version for production: http://code.jquery.com/jquery-1.9.1.min.js<br />
<br />
This has become the standard, and makes perfect sense. The minified file name contains the ".min". And they both contain the version number - this way there's never a web browser having a stale version in the cache.<br />
<br />
ExtJS files:<br />
ext-all.js: The minified JS file.<br />
ext-all-debug.js: The original source code, comments stripped. Useless.<br />
ext-all-debug-w-comments.js: The original source code.<br />
<br />
What I (and probably every other ExtJS developer) need is a version that contains code with input checking to throw as early as possible, with a meaningful message. You know... common programming practices... absolutely mandatory for any library code.<br />
<br /></div>
<h3>
Summing it up</h3>
<div>
As it is now, you have to test every single functionality to be sure it works. Upgrading an app from ExtJS 3 to ExtJS 4 is no fun. Lots of things don't work anymore, but you have to figure out a) which and b) what to change. And the same will be true for version 5, 6 and 7. And any minor upgrade can break things too.</div>
<br />
If you have ui tests then at least you will know about some defects early. But you still need to figure out the hard way how to fix them. And writing and maintaining automated ui tests is another full time job.<br />
<br />
Please, Sencha, do yourself and every of the 2 million developers a big favor and add error checking to your libraries, and strip it in the "min"-ified production version for equal performance and file size.<br />
<br />Anonymoushttp://www.blogger.com/profile/16815999018553645136noreply@blogger.com2tag:blogger.com,1999:blog-2415041862544909856.post-87366297287554925262013-04-03T07:01:00.000-07:002014-03-10T20:27:39.263-07:00Java: Replace Apache Commons DBCPUntil recently I used to use the <a href="http://commons.apache.org/proper/commons-dbcp/" target="_blank">Apache Commons Database Connection Pool</a> in my JDBC Java applications. Then there was an incident, and I had to replace it with <a href="https://github.com/swaldman/c3p0" target="_blank">c3p0</a>. Here are my reasons.<br />
<br />
I never gave it much thought. A db connection pool just manages the connections... handing them out and taking them back. How hard can that be? It's not something I want to spend time on. There's that project from Apache, and I like their HTTP server. So it's probably a safe bet. I thought.<br />
<br />
<h3>
What's the quality of commons-dbcp?</h3>
The <a href="http://stackoverflow.com/tags/apache-commons-dbcp/hot" target="_blank">hottest</a> question about
commons-dbcp
on stackoverflow is <a href="http://stackoverflow.com/questions/520585/connection-pooling-options-with-jdbc-dbcp-vs-c3p0" target="_blank">this one</a>: Someone asking whether to use Apache DBCP or C3P0.<br />
<br />
The top answer with many agreements says:<br />
<blockquote class="tr_bq">
<b>DBCP is out of date and not production grade.</b> Some time back we conducted an in-house analysis of the two, creating a test fixture which generated load and concurrency against the two to assess their suitability under real life conditions.</blockquote>
<blockquote class="tr_bq">
<b>DBCP consistently generated exceptions</b> into our test application and struggled to reach levels of performance which C3P0 was more than capable of handling without any exceptions.</blockquote>
<blockquote class="tr_bq">
C3P0 also robustly handled DB disconnects and transparent reconnects on resume whereas <b>DBCP never recovered connections</b> if the link was taken out from beneath it. Worse still DBCP was <b>returning Connection objects</b> to the application for which the underlying transport had <b>broken</b>.</blockquote>
<blockquote class="tr_bq">
Since then we have used C3P0 in 4 major heavy-load consumer web apps and have never looked back.</blockquote>
The post (from 2009) then goes on and says that recently there was some work on commons-dbcp. Now, 4 years later, what happened in the meantime?<br />
<br />
<h3>
What's the status of commons-dbcp?</h3>
The website was last updated 2.5 years ago.<br />
<br />
The last release 1.4 is 3 years old, 1.4.1 is a snapshot.<br />
<br />
The website is broken: <br />
<div>
<ul>
<li>It has dead links (for example to the official Javadoc). </li>
<li>The logo image on the left doesn't load.</li>
<li>And it has character set issues to display the text (those ? signs). </li>
</ul>
Maybe these errors are in place when the website url changed from http://commons.apache.org/dbcp/ to the one it redirects to. Anyway, they don't seem to be important to be fixed.<br />
<br />
Commons-dbcp is a subversion repo at svn.apache.org (C3P0 is on GitHub).<br />
<br /></div>
<h3>
My issue</h3>
<div>
The reason why I had to kick
commons-dbcp
out was that it broke my application. After a couple hours it stopped handing out connections, and all threads were in WAITING state.</div>
<blockquote class="tr_bq">
<span style="color: #990000;"><b>org.apache.commons.pool.impl.GenericObjectPool.borrowObject(GenericObjectPool.java:1104)</b></span></blockquote>
<div>
After some reading I tried c3p0, run long running high concurrency tests where
commons-dbcp
choked, and it all worked fine. And after some more reading I was convinced that the problem was solved.<br />
<br /></div>
<h3>
But it works for me...</h3>
<div>
Maybe it does. Maybe you just don't hit it hard enough yet. And maybe you don't get to see all errors. As reported by others there are issues with commons-dbcp, and it looks like a dead project. Also, <a href="http://www.hibernate.org/" target="_blank">Hibernate</a> comes with c3p0, not commons-dbcp.<br />
<br /></div>
<h3>
But dbcp is faster ...</h3>
<div>
I've seen statistics where one or the other product stands out. Any connection pool is fast enough for me... as long as it keeps doing its main job.<br />
<br /></div>
<h3>
Other alternatives</h3>
<div>
I did not look into other, newer products because I'm happy with one that has been in use for long time.<br />
<br />
Now there's the <a href="http://tomcat.apache.org/tomcat-7.0-doc/jdbc-pool.html" target="_blank">Apache Tomcat JDBC Connection Pool</a> and <a href="http://feenixtech.blogspot.ro/2012/04/jdbc-connection-pools-replacing-commons.html" target="_blank">this blog post</a> talks about feeling uncomfortable with commons-dbcp and replacing it with tomcat-jdbc.<br />
<br />
And there's <a href="http://jolbox.com/" target="_blank">BoneCP</a> which says how much faster it is than the others. It started in 2009, had no release in 2 years, and is at version v0.7.1.<br />
<br /></div>
<h3>
I want to replace commons-dbcp with c3p0!</h3>
<div>
Here's what you have to do if you're using Maven and Spring, connecting to MySQL:<br />
<br />
1. Replace the commons-jdbc dependency with this:<br />
<blockquote>
<pre><dependency>
<groupId>com.mchange</groupId>
<artifactId>c3p0</artifactId>
<version>0.9.2.1</version>
</dependency>
</pre>
</blockquote>
2. Replace some words in the data source bean:<br />
a) change the class to com.mchange.v2.c3p0.ComboPooledDataSource<br />
b) change the word "driverClassName" to "driverClass"<br />
c) change the word "url" to "jdbcUrl"<br />
d) change the word "username" to "user"<br />
<br />
Example:
<br />
<blockquote>
<pre><bean id="geoDataSource" destroy-method="close" class="com.mchange.v2.c3p0.ComboPooledDataSource">
<property name="driverClass" value="com.mysql.jdbc.Driver"/>
<property name="jdbcUrl" value="jdbc:mysql://localhost/db"/>
<property name="user" value="myUser"/>
<property name="password" value="myPassword"/>
</bean>
</pre>
</blockquote>
</div>
<h3>
Conclusions</h3>
<div>
<ol>
<li>You might want to consider replacing commons-dbcp also. Maybe with c3p0, it works for me.</li>
<li>Maybe commons-dbcp should be moved to their <a href="http://attic.apache.org/">attic</a>.
</li>
</ol>
<br />
Update 2014-03-11<br />
C3P0 is under active development on GitHub, and the author nicely replied to my questions on StackOverflow and on the mailing list within hours. Thumbs up.</div>
Anonymoushttp://www.blogger.com/profile/16815999018553645136noreply@blogger.com6tag:blogger.com,1999:blog-2415041862544909856.post-71065843675381415832013-03-18T19:39:00.001-07:002014-11-05T05:33:21.402-08:00Dependency Injection: @Resource, @Inject, @Autowired<h3>
Overview</h3>
When using <a href="http://www.springsource.org/spring-framework">Spring</a> there's the choice of 3 annotations for injecting resources with <span style="color: #38761d;">advantages</span> and <span style="color: #990000;">disadvantages</span>:<br />
<ol>
<li>@Autowired<br />The original, "proprietary" annotation from Spring.<br /><span style="color: #990000;">- not standard, Spring proprietary</span><br /><span style="color: #38761d;">+ resolves by type<br />+ for optional dependencies </span></li>
<li>@Resource<br />The <a href="http://jcp.org/en/jsr/detail?id=250">JSR-250</a> annotation<br /><span style="color: #38761d;">+ standard dependency injection</span><br /><span style="color: #990000;">- resolves by name, fallback by type<br />- not for optional dependencies </span></li>
<li>@Inject<br />The <a href="https://code.google.com/p/atinject/">JSR-330</a> annotation
<br />
<span style="color: #38761d;">+ resolves by type
<br />
+ standard dependency injection
</span><br />
<span style="color: #38761d;">+ for optional dependencies</span>
<span style="color: #990000;">(- slightly different API) </span></li>
</ol>
<h3>
Injection by type or by name</h3>
When the @Resource annotation was introduced, I switched to it to not have Spring as a hard dependency. I never used dependency resolving by name, and relied on the fallback by type. This bit me a couple of times with code like:<br />
<br />
@Resource<br />
private SomeVeryDescriptiveClassName className;<br />
<br />
when a class with the name ClassName existed because then that was injected, or attempted to be injected.<br />
<br />
Now I'll switch from @Resource to the newer @Inject which does exactly what I want.<br />
<br />
<h3>
Optional dependencies</h3>
Unfortunately, both of the standard Java DI annotations lack the attribute that @Autowired provided: @Autowired(required=false) <br />
<br />
Every couple of months I find myself in the situation where I really need an optional dependency. Not having exactly one implementation throws (having multiple and using the @Qualifier annotation works too).<br />
<br />
An example is an interface provided by a framework, and the userland code may provide an implementation if desired.<br />
<br />
Without optional injections one way to solve this is with the "priority" int. I use this concept when multiple implementations of an interface might exist, maybe including a system provided default implementation, and only the most important one should be used:<br />
<br />
public interface Foo {<br />
int getPriority();<br />
void doSomething();<br />
}<br />
<br />
Each implementation returns a number, and the highest one wins in the injection:<br />
<br />
@Inject<br />
private void setFoos(List<foo> foos) {</foo><br />
//choose<br />
}<br />
<br />
I prefer to keep it short, and thus kept using the proprietary @Autowired annotation in these rare cases. But @Inject <a href="http://docs.jboss.org/weld/reference/latest/en-US/html/injection.html#lookup" target="_blank">has its way</a> for handling this too (thanks to rliesenfeld's comment):<br />
<br />
@Inject Instance< Foo> fooSource;<br />
Foo foo =
fooSource
.get(); //returns null or the instance<br />
<br />
Unfortunately you need Java EE for the Instance interface.<br />
<br />
<h3>
Conclusion</h3>
@Inject is what I'll use in general from now on, and what probably most situations ask for.<br />
<br />
<a href="http://blogs.sourceallies.com/2011/08/spring-injection-with-resource-and-autowired/" target="_blank">This blog post</a> shows the differences of dependency injection (by type or by name, with @Qualifier) in detail.<br />
<br />
Note: To use the @Inject annotation the following dependency is required:<br />
<pre class="lang-java prettyprint prettyprinted" style="-webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px; background-color: #eeeeee; background-position: initial initial; background-repeat: initial initial; border: 0px; color: black; font-family: Consolas, Menlo, Monaco, 'Lucida Console', 'Liberation Mono', 'DejaVu Sans Mono', 'Bitstream Vera Sans Mono', 'Courier New', monospace, serif; font-size: 14px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: 18px; margin: 0px 0px 10px; max-height: 600px; orphans: auto; overflow: auto; padding: 5px; text-align: left; text-indent: 0px; text-transform: none; vertical-align: baseline; widows: auto; width: auto; word-spacing: 0px;"><code style="background-color: #eeeeee; background-position: initial initial; background-repeat: initial initial; 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; margin: 0px; padding: 0px; vertical-align: baseline;"><span class="pun" style="background-color: transparent; background-position: initial initial; background-repeat: initial initial; border: 0px; color: black; font-size: 14px; margin: 0px; padding: 0px; vertical-align: baseline;"><</span><span class="pln" style="background-color: transparent; background-position: initial initial; background-repeat: initial initial; border: 0px; color: black; font-size: 14px; margin: 0px; padding: 0px; vertical-align: baseline;">dependency</span><span class="pun" style="background-color: transparent; background-position: initial initial; background-repeat: initial initial; border: 0px; color: black; font-size: 14px; margin: 0px; padding: 0px; vertical-align: baseline;">></span><span class="pln" style="background-color: transparent; background-position: initial initial; background-repeat: initial initial; border: 0px; color: black; font-size: 14px; margin: 0px; padding: 0px; vertical-align: baseline;">
</span><span class="pun" style="background-color: transparent; background-position: initial initial; background-repeat: initial initial; border: 0px; color: black; font-size: 14px; margin: 0px; padding: 0px; vertical-align: baseline;"><</span><span class="pln" style="background-color: transparent; background-position: initial initial; background-repeat: initial initial; border: 0px; color: black; font-size: 14px; margin: 0px; padding: 0px; vertical-align: baseline;">groupId</span><span class="pun" style="background-color: transparent; background-position: initial initial; background-repeat: initial initial; border: 0px; color: black; font-size: 14px; margin: 0px; padding: 0px; vertical-align: baseline;">></span><span class="pln" style="background-color: transparent; background-position: initial initial; background-repeat: initial initial; border: 0px; color: black; font-size: 14px; margin: 0px; padding: 0px; vertical-align: baseline;">javax</span><span class="pun" style="background-color: transparent; background-position: initial initial; background-repeat: initial initial; border: 0px; color: black; font-size: 14px; margin: 0px; padding: 0px; vertical-align: baseline;">.</span><span class="pln" style="background-color: transparent; background-position: initial initial; background-repeat: initial initial; border: 0px; color: black; font-size: 14px; margin: 0px; padding: 0px; vertical-align: baseline;">inject</span><span class="pun" style="background-color: transparent; background-position: initial initial; background-repeat: initial initial; border: 0px; color: black; font-size: 14px; margin: 0px; padding: 0px; vertical-align: baseline;"></</span><span class="pln" style="background-color: transparent; background-position: initial initial; background-repeat: initial initial; border: 0px; color: black; font-size: 14px; margin: 0px; padding: 0px; vertical-align: baseline;">groupId</span><span class="pun" style="background-color: transparent; background-position: initial initial; background-repeat: initial initial; border: 0px; color: black; font-size: 14px; margin: 0px; padding: 0px; vertical-align: baseline;">></span><span class="pln" style="background-color: transparent; background-position: initial initial; background-repeat: initial initial; border: 0px; color: black; font-size: 14px; margin: 0px; padding: 0px; vertical-align: baseline;">
</span><span class="pun" style="background-color: transparent; background-position: initial initial; background-repeat: initial initial; border: 0px; color: black; font-size: 14px; margin: 0px; padding: 0px; vertical-align: baseline;"><</span><span class="pln" style="background-color: transparent; background-position: initial initial; background-repeat: initial initial; border: 0px; color: black; font-size: 14px; margin: 0px; padding: 0px; vertical-align: baseline;">artifactId</span><span class="pun" style="background-color: transparent; background-position: initial initial; background-repeat: initial initial; border: 0px; color: black; font-size: 14px; margin: 0px; padding: 0px; vertical-align: baseline;">></span><span class="pln" style="background-color: transparent; background-position: initial initial; background-repeat: initial initial; border: 0px; color: black; font-size: 14px; margin: 0px; padding: 0px; vertical-align: baseline;">javax</span><span class="pun" style="background-color: transparent; background-position: initial initial; background-repeat: initial initial; border: 0px; color: black; font-size: 14px; margin: 0px; padding: 0px; vertical-align: baseline;">.</span><span class="pln" style="background-color: transparent; background-position: initial initial; background-repeat: initial initial; border: 0px; color: black; font-size: 14px; margin: 0px; padding: 0px; vertical-align: baseline;">inject</span><span class="pun" style="background-color: transparent; background-position: initial initial; background-repeat: initial initial; border: 0px; color: black; font-size: 14px; margin: 0px; padding: 0px; vertical-align: baseline;"></</span><span class="pln" style="background-color: transparent; background-position: initial initial; background-repeat: initial initial; border: 0px; color: black; font-size: 14px; margin: 0px; padding: 0px; vertical-align: baseline;">artifactId</span><span class="pun" style="background-color: transparent; background-position: initial initial; background-repeat: initial initial; border: 0px; color: black; font-size: 14px; margin: 0px; padding: 0px; vertical-align: baseline;">></span><span class="pln" style="background-color: transparent; background-position: initial initial; background-repeat: initial initial; border: 0px; color: black; font-size: 14px; margin: 0px; padding: 0px; vertical-align: baseline;">
</span><span class="pun" style="background-color: transparent; background-position: initial initial; background-repeat: initial initial; border: 0px; color: black; font-size: 14px; margin: 0px; padding: 0px; vertical-align: baseline;"><</span><span class="pln" style="background-color: transparent; background-position: initial initial; background-repeat: initial initial; border: 0px; color: black; font-size: 14px; margin: 0px; padding: 0px; vertical-align: baseline;">version</span><span class="pun" style="background-color: transparent; background-position: initial initial; background-repeat: initial initial; border: 0px; color: black; font-size: 14px; margin: 0px; padding: 0px; vertical-align: baseline;">></span><span class="lit" style="background-color: transparent; background-position: initial initial; background-repeat: initial initial; border: 0px; color: maroon; font-size: 14px; margin: 0px; padding: 0px; vertical-align: baseline;">1</span><span class="pun" style="background-color: transparent; background-position: initial initial; background-repeat: initial initial; border: 0px; color: black; font-size: 14px; margin: 0px; padding: 0px; vertical-align: baseline;"></</span><span class="pln" style="background-color: transparent; background-position: initial initial; background-repeat: initial initial; border: 0px; color: black; font-size: 14px; margin: 0px; padding: 0px; vertical-align: baseline;">version</span><span class="pun" style="background-color: transparent; background-position: initial initial; background-repeat: initial initial; border: 0px; color: black; font-size: 14px; margin: 0px; padding: 0px; vertical-align: baseline;">></span><span class="pln" style="background-color: transparent; background-position: initial initial; background-repeat: initial initial; border: 0px; color: black; font-size: 14px; margin: 0px; padding: 0px; vertical-align: baseline;">
</span><span class="pun" style="background-color: transparent; background-position: initial initial; background-repeat: initial initial; border: 0px; color: black; font-size: 14px; margin: 0px; padding: 0px; vertical-align: baseline;"></</span><span class="pln" style="background-color: transparent; background-position: initial initial; background-repeat: initial initial; border: 0px; color: black; font-size: 14px; margin: 0px; padding: 0px; vertical-align: baseline;">dependency</span><span class="pun" style="background-color: transparent; background-position: initial initial; background-repeat: initial initial; border: 0px; color: black; font-size: 14px; margin: 0px; padding: 0px; vertical-align: baseline;">></span></code></pre>
<br />
The import for the Instance interface is from Java EE: <br />
<span style="font-family: "Courier New",Courier,monospace;">import javax.enterprise.inject.Instance;</span><br />
<br />Anonymoushttp://www.blogger.com/profile/16815999018553645136noreply@blogger.com2tag:blogger.com,1999:blog-2415041862544909856.post-68419629980376599722013-02-08T04:48:00.001-08:002013-02-08T04:48:53.842-08:00Using Bootstrap is cheating!<span style="font-size: large;">Recently I've launched the beta of a <a href="http://www.surfr.co/">new website</a>. The instant response I got from my programmer buddies was <span style="color: #999999;">(</span><span style="font-size: large;"><span style="color: #999999;">did you click? </span><span style="font-size: large;"><span style="color: #999999;">you're pro</span><span style="font-size: large;"><span style="color: #999999;">bably</span><span style="font-size: large;"><span style="color: #999999;"> a programmer too</span><span style="font-size: large;"><span style="color: #999999;">... does it match your first thought?)</span> </span></span></span></span></span>a consistent "Bootstrap!" shout. </span><br />
<br />
My first impression was that it means "I know it too, I'm up to date". Maybe that's part of it, but it's certainly not all. The feeling I have now is that using <a href="http://twitter.github.com/bootstrap/">Bootstrap</a> is cheating.<br />
<br />
Just like most people think that work must be hard and no fun, otherwise it's not work, do people believe that making a nice, consistent UI must be troublesome and hard? Or is using the standard theme without customization not acceptable?<br />
<br />
For other technologies I never got such a reaction in the past. "HTML!" or "ExtJS!" ... never heard.<br />
<br />
Bootstrap isn't perfect, but it serves its main purpose well. At a very low cost it brings a consistent, clean and clear user interface. Users want intuitive, standard interfaces, common patterns. Figuring out how each site works with a hand-knitted GUI sucks too much energy.<br />
<br />
This is a standard <a href="http://www.sencha.com/products/extjs">ExtJS</a> 4 form as showcased on their website:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="http://3.bp.blogspot.com/-2vPH629u0aQ/URLQ8WHwWeI/AAAAAAAAADQ/2_QvgzgNAds/s1600/standard-extjs-form.gif" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="http://3.bp.blogspot.com/-2vPH629u0aQ/URLQ8WHwWeI/AAAAAAAAADQ/2_QvgzgNAds/s1600/standard-extjs-form.gif" height="187" width="320" /></a></div>
<br />
Notice something? Pretty standard, isn't it? User interfaces looked like this for decades. The problem: it's not awesome.<br />
<br />
It wastes too many brain cycles to figure out which button to press. I've certainly pressed the wrong one in the past. And for the users who have to fall back to a secondary language because there is no translation for their primary language yet, it's worse:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="http://4.bp.blogspot.com/-zuhNjdhYZog/URLVRQ--AUI/AAAAAAAAADg/TFLWOyGtAoE/s1600/standard-extjs-form-de.gif" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="http://4.bp.blogspot.com/-zuhNjdhYZog/URLVRQ--AUI/AAAAAAAAADg/TFLWOyGtAoE/s1600/standard-extjs-form-de.gif" height="187" width="320" /></a></div>
<br />
Now compare this to bootstrap buttons:<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="http://3.bp.blogspot.com/-krUhmsCrRG4/URLX8Dk5ZKI/AAAAAAAAADo/wdCwb14NoOU/s1600/form-buttons-chinese.gif" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="http://3.bp.blogspot.com/-krUhmsCrRG4/URLX8Dk5ZKI/AAAAAAAAADo/wdCwb14NoOU/s1600/form-buttons-chinese.gif" /></a></div>
I'm not sure I've chosen the correct Google translate offerings... and it doesn't even matter. Color and size suggest the meaning already.<br />
<br />
The aforementioned <a href="http://surfr.co/">Surfr platform</a> uses the traditional "..." on button labels to indicate that no harm is done pressing this button, another screen with information or options will appear first. For actions that perform data modifications (such as saving a record) an exclamation mark is appended to the action's name: "Save!". And actions that can't be undone are additionally styled with a warning color:<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="http://2.bp.blogspot.com/-HXT-6Nubub8/URLa_reShvI/AAAAAAAAADw/uV7Yb8zm6Y8/s1600/punctuation-on-buttons.gif" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="http://2.bp.blogspot.com/-HXT-6Nubub8/URLa_reShvI/AAAAAAAAADw/uV7Yb8zm6Y8/s1600/punctuation-on-buttons.gif" /></a></div>
<br />
The critical among you will say "you can do this with ExtJS too". Of
course you can. You can do everything from scratch. Fact is, the average
site using Bootstrap is easier to read and use compared to the average
self-made ui site - at almost no development cost.<br />
<br />
I like standards. I like simplicity. I hate to deal with css and browser issues. Conclusion: Call me a cheater... but I like Bootstrap.Anonymoushttp://www.blogger.com/profile/16815999018553645136noreply@blogger.com0tag:blogger.com,1999:blog-2415041862544909856.post-62783685444920845552013-02-06T20:29:00.001-08:002013-02-14T03:56:37.166-08:00Where do you register your domains?<span style="font-size: large;">My posts are usually rants and complaints. If there's nothing wrong, there's no reason for change, so why bother to write. Not so this one, it's full of praise and worship.</span><br />
<br />
Nah, just kidding. It starts with rant.<br />
<br />
<a href="http://www.namesilo.com/images/no_hidden_fees.gif" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"><img border="0" src="http://www.namesilo.com/images/no_hidden_fees.gif" /></a>There are the classical types for dishonorable businesses. Telco is the worst that comes to mind. Contract lock in, intransparent calling and roaming costs, etc.<br />
<br />
Another bad one is domain name registration... or at least used to be. It started for me in the good old days when internic (now Network Solutions) was the only registrar for com/net/org. Their address was at internic.net, and a cunning company from Australia registered internic.com, tricking the visitors into believing it's the real thing. The gangster <a href="http://news.cnet.com/Domain-registry-charged-with-fraud/2100-1023_3-210804.html">Peter Zmijewski</a> was later charged with fraud, and <a href="http://www.digestiblelaw.com/blog.aspx?entry=616">apparently</a> some 13k victims got money back. Not me.<br />
<br />
Today, there are a ton of official registrars who offer perfectly legal domain registration. The price is usually slightly above what they need to pay to the registry - for .com that is still Network Solutions at <b>$6 per year</b>. Just like Telco it's a tough business with small margins. Some charge a lot and can do it thanks to their market position. For example Network Solutions they ask for $34.99. Crazy. GoDaddy is very popular which allows them to charge $13.17, which means $7 to keep. Others offer low prices in the 1 digit range... and to maximize profit, they try to trick the customer in several ways. Not so <a href="http://www.namesilo.com/">namesilo</a>.<br />
<br />
Today I've registered the 2nd domain name with namesilo. <a href="http://www.namesilo.com/why_us.php">Reading their website is a pleasure</a>:<br />
<ul><a href="http://3.bp.blogspot.com/--1rFzHk-RGA/URMNGeIvxRI/AAAAAAAAAEY/FMqfHxSvS5o/s1600/namesilo.png" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"><img border="0" src="http://3.bp.blogspot.com/--1rFzHk-RGA/URMNGeIvxRI/AAAAAAAAAEY/FMqfHxSvS5o/s1600/namesilo.png" /></a>
<li>Cheap: $8.99 per year (that means $3 to keep for themselves)</li>
<li>Renewals cost the same. (That's where other registrars try to cheat. <b>First year cheap, then whoops.</b> Hard to switch.)</li>
<li>Extra features are included for free. (Whois privacy, preventing unauthorized record changes. That's where others try to sneak in costly services, possibly free the first year, and then charged automatically.)</li>
<li>No hidden cost. (I'm repeating myself here, but I just have to say it.)</li>
</ul>
<b>That's the kind of business model I like.</b> Just domains, no hosting and up-selling and crap. Fair, transparent, clear.<br />
<br />
So if you see an offering like GoDaddy is currently advertising on Google Adwords "$2.95 COMs at Go Daddy" then you know something is wrong. Either you'll pay in the long run, or you have to buy their hosting, or so.<br />
<br />
For the <a href="http://www.flowstopper.org/2012/11/how-important-is-domain-name-today.html">trendy .co domains</a> I use namecheap. Don't like them, they're exactly the kind I described above. But namesilo doesn't do .co.<br />
<br />
<br />
<br />Anonymoushttp://www.blogger.com/profile/16815999018553645136noreply@blogger.com1tag:blogger.com,1999:blog-2415041862544909856.post-60813997147755232172013-01-28T13:48:00.000-08:002013-02-06T17:07:32.170-08:00When to use Gmail's SMTP in your app and when not<br />
<div class="separator" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em; text-align: center;">
<img border="0" src="http://www.pcc.edu/resources/tss/new-email/images/Icon-Gmail.png" height="200" width="200" /></div>
<br />
<span style="font-size: large;">This post is about the very legitimate automated emails generated by any application, such as for transactions and signups. Getting these delivered to the inbox (instead of spambox or nirvana) is the goal. </span><br />
<br />
<h2>
The short answer: </h2>
Sooner or later you may hit the sending limit. It's not when you deploy, and maybe not while beta testing. So better know the limits, risks and alternatives.<br />
<br />
<h2>
The longer answer:</h2>
If your sender address is hosted on <a href="http://www.gmail.com/">Gmail</a> then using their SMTP server is the obvious choice because:
<br />
<ul>
<li>You already have access to it</li>
<li>High availability</li>
<li>Unlikely that Gmail's smtp servers get added to block lists such as <a href="http://www.spamhaus.org/sbl/">this one</a></li>
</ul>
<br />
<h3>
How to connect to Gmail SMTP</h3>
All you need is the <a href="http://support.google.com/mail/bin/answer.py?hl=en&answer=78799">following information</a>, and an SMTP library for your programming language:
<br />
<ul>
<li>host: smtp.gmail.com</li>
<li>port: 465</li>
<li>ssl: yes</li>
<li>user: <your-email-address-at-google example.com=""></your-email-address-at-google></li>
<li>password: <your-matching-password></your-matching-password></li>
</ul>
<div>
The email address you use to log in must be a real account, <b>not an alias</b>. If you prefer to send the address from a different address, use the "from" field. Not modifying the "from" and "reply-to" increases your chances of getting delivered to the inbox.</div>
<br />
You test it, email delivers, so you deploy your app, done.<br />
<br />
<h3>
Errors to expect</h3>
Soon after, your beta testers report to not receive any email. Checking your logs finds errors such as <i>"<b>550 5.4.5 Daily sending quota exceeded.</b>"</i> or <i>"535, response: 5.7.1 Please log in with your web browser and then try again."</i>. What happened?<br />
<br />
<h3>
3 types of Gmail accounts</h3>
There are three types of Gmail addresses:
<br />
<ol>
<li>The common Gmail domains: anything @ gmail</li>
<li>Google Apps for free: yourname @ yourdomain</li>
<li>Google Apps pro: yourname @ yourdomain</li>
</ol>
<div>
If you go and sign up for a new Gmail address from your desktop, then try sending mail from your (remote) server location, you'll get the 535 error quickly (it's the typical spammer pattern). You need to verify your account by SMS, and mailing goes on. For a short moment. It appears that such accounts can only send to a handful of different email addresses per day. I was not able to find official statements and numbers. The number is probably so low for new accounts, so if you have an established one it may work longer.</div>
<div>
<br /></div>
<div>
If you have your own domain set up for Gmail then the limit is higher. It makes sense since you have a public whois record. Google disabled signups for the free apps service a couple weeks ago. That's probably why I cannot find official information about the limits. The number of recipients per day is quoted as 500 on the internet. If you have such an account already then you can continue using it.</div>
<div>
<br /></div>
<div>
For the paid account the <a href="http://support.google.com/a/bin/answer.py?hl=en&answer=166852&from=166862&rd=1">official page</a> says 2000 unique, external recipients per day. </div>
<div>
<br /></div>
<h3>
Other risks</h3>
<div>
The official page has another fact:</div>
<blockquote class="tr_bq">
"The value of these limits may change without notice in order to protect Google’s infrastructure"</blockquote>
<div>
Also, I've found unofficial/unverified information about Google lowering the daily send limit on high bounce rates. This makes perfect sense; spammers have high bounce rates. <b>This is an open door to malicious users of your app</b>: sign up with a couple invalid addresses, and your email system may be interrupted for a while.</div>
<div>
<br /></div>
<br />
<h3>
Using your own SMTP</h3>
If you decide now that Gmail SMTP is not for you, there are some things to consider with your own.<br />
<br />
If you access the SMTP of your provider, then you may face similar limits there. After all your provider has to make sure their customers don't spam, and not the whole server gets blacklisted. But this can and does happen nevertheless: Either because one of the other users spammed, or because one account was hijacked and abused. As a result your email messages may be accepted by the SMTP, but never make it to their destination. Maybe you get bounces, maybe not.<br />
<br />
Be sure to create a <a href="http://support.google.com/a/bin/answer.py?hl=en&answer=33786">Sender Policy Framework record</a>.<br />
<br />
<h2>
Conclusions</h2>
<h3>
A combined approach</h3>
I still believe that using Gmail's outgoing mailserver has its advantages. They are reliable, and in case of denial they return clear status codes. A solution with Gmail as primary, and your server as fallback, sounds like a good idea to me.<br />
<br />
<h3>
Further reading</h3>
Google's <a href="http://support.google.com/mail/bin/answer.py?hl=en&answer=81126">Bulk Senders Guidelines</a> has more useful information to get delivered.<br />
<br />
<h3>
Not for marketing</h3>
Given the limits and risks, I'd definitely not use Gmail for sending anything that could be marked as spam by the receivers. Marketing, newsletters, even if the user at some point actively asked for it. Only send high priority mail such as transaction confirmations though Gmail SMTP.
Anonymoushttp://www.blogger.com/profile/16815999018553645136noreply@blogger.com1