tag:blogger.com,1999:blog-58665145773402670462024-03-20T10:53:05.334+02:00Alexander Cherednichenko's blogthoughts on technology and software developmentAlexanderhttp://www.blogger.com/profile/10093762646999402082noreply@blogger.comBlogger76125tag:blogger.com,1999:blog-5866514577340267046.post-74249259716415045762013-10-27T20:31:00.003+02:002013-10-27T20:31:45.574+02:00Two talks at local Software Development meetup: me and Pavel Knorr<div dir="ltr" style="text-align: left;" trbidi="on">
<div class="markdown-here-wrapper" data-md-original="%3Cp%3EHello%2C%3C%2Fp%3E%3Cp%3E%3Cbr%3E%3C%2Fp%3E%3Cp%3EBoth%20Pavel%20Knorr%20and%20myself%2C%20from%20Logicify%2C%20were%20having%20talks%20at%20local%20IT-meetup%20last%20Thursday.%20That%20was%20quite%20fun%2C%20thank%20to%20DataArt%20Kherson%20for%20organizing%20people%20and%20facility.%3C%2Fp%3E%3Cp%3E%3Cbr%3E%3C%2Fp%3E%3Cp%3EThanks%20to%20Pavel%20for%20making%20up%20his%20excellent%20presentation%20with%20code%20samples%2C%20and%20to%20everyone%20working%20on%20our%20nodejs-sample%20application.%3C%2Fp%3E%3Cp%3E%3Cbr%3E%3C%2Fp%3E%3Cp%3EHere%20are%20the%20relevant%20links%3A%3C%2Fp%3E%3Cp%3E%3Cbr%3E%3C%2Fp%3E%3Cp%3E1.%26nbsp%3B%3Ca%20href%3D%22https%3A%2F%2Fgithub.com%2FLogicify%2Fnodejs-sample-task%22%3Ehttps%3A%2F%2Fgithub.com%2FLogicify%2Fnodejs-sample-task%3C%2Fa%3E%26nbsp%3B-%20source%20code%20of%20the%20sample%20app.%20We%20also%20use%20it%20as%20'seed'%2C%20or%20an%20'archetype'%20for%20starting%20new%20apps%20of%20the%20same%20structure.%26nbsp%3B%3C%2Fp%3E%3Cp%3E1.%26nbsp%3B%3Ca%20href%3D%22https%3A%2F%2Fdocs.google.com%2Fpresentation%2Fd%2F1XW8suMG4hpzmccoKtvtLpytVgZLyVPZqZgrqCGnyNUY%2Fpresent%23slide%3Did.g121b56501_148%22%3Ehttps%3A%2F%2Fdocs.google.com%2Fpresentation%2Fd%2F1XW8suMG4hpzmccoKtvtLpytVgZLyVPZqZgrqCGnyNUY%2Fpresent%23slide%3Did.g121b56501_148%3C%2Fa%3E%26nbsp%3B**Russian%20language**%20Slides%20for%20the%20Pavel's%20talk%20about%20basics%20and%20caveats%20of%20Node.js.%20It%20would%20be%20best%20viewed%20with%20the%20accompanying%20recording%20of%20the%20talk%2C%20and%20if%20you%20have%20some%20background%20in%20client-side%20javascript%20and%2For%20serverside%20programming%20(like%20java).%3C%2Fp%3E%3Cp%3E1.%26nbsp%3B%3Ca%20href%3D%22https%3A%2F%2Fdocs.google.com%2Fpresentation%2Fd%2F1Osy7XQd9LuY7npicwK-r37cNOFUW0No3AwzEbEmRNqQ%2Fpresent%23slide%3Did.p%22%3Ehttps%3A%2F%2Fdocs.google.com%2Fpresentation%2Fd%2F1Osy7XQd9LuY7npicwK-r37cNOFUW0No3AwzEbEmRNqQ%2Fpresent%23slide%3Did.p%3C%2Fa%3E%26nbsp%3B**Russian%20language**%20Slides%20for%20my%20presentation%20on%20Node.js%20and%20unittesting.%20Would%20be%20best%20if%20the%20reader%20woud%20understand%20the%20concepts%20of%20the%20unit%20testing%20(mocks%2C%20verification%2C%20structure%2C%20goal%20of%20unittesting%2C%20level%20of%20granularity%2C%20usual%20terminology)%2C%20thought%20that's%20not%20really%20required.%26nbsp%3B%3C%2Fp%3E%3Cp%3E%3Cbr%3E%3C%2Fp%3E%3Cp%3EHappy%20to%20help%20if%20you%20have%20questions!%26nbsp%3B%3C%2Fp%3E%3Cp%3E%3Cbr%3E%3C%2Fp%3E%3Cp%3EBest%2C%26nbsp%3B%3C%2Fp%3E%3Cp%3EAlex.%3C%2Fp%3E" data-md-url="http://www.blogger.com/blogger.g?blogID=5866514577340267046#editor/target=post;postID=7424925971641504576" id="markdown-here-wrapper-952843">
<div style="margin: 1.2em 0px !important;">
Hello,</div>
<div style="margin: 1.2em 0px !important;">
Both Pavel Knorr and myself, from Logicify, were having talks at local IT-meetup last Thursday. That was quite fun, thank to DataArt Kherson for organizing people and facility.</div>
<div style="margin: 1.2em 0px !important;">
Thanks to Pavel for making up his excellent presentation with code samples, and to everyone working on our nodejs-sample application.</div>
<div style="margin: 1.2em 0px !important;">
Here are the relevant links:</div>
<ol style="margin: 1.2em 0px; padding-left: 2em;">
<li style="margin: 0.5em 0px;"><a href="https://github.com/Logicify/nodejs-sample-task"></a><a href="https://github.com/Logicify/nodejs-sample-task">https://github.com/Logicify/nodejs-sample-task</a> - source code of the sample app. We also use it as ‘seed’, or an ‘archetype’ for starting new apps of the same structure. </li>
<li style="margin: 0.5em 0px;"><a href="https://docs.google.com/presentation/d/1XW8suMG4hpzmccoKtvtLpytVgZLyVPZqZgrqCGnyNUY/present#slide=id.g121b56501_148"></a><a href="https://docs.google.com/presentation/d/1XW8suMG4hpzmccoKtvtLpytVgZLyVPZqZgrqCGnyNUY/present#slide=id.g121b56501_148">https://docs.google.com/presentation/d/1XW8suMG4hpzmccoKtvtLpytVgZLyVPZqZgrqCGnyNUY/present#slide=id.g121b56501_148</a> <strong>Russian language</strong> Slides for the Pavel’s talk about basics and caveats of Node.js. It would be best viewed with the accompanying recording of the talk, and if you have some background in client-side javascript and/or serverside programming (like java).</li>
<li style="margin: 0.5em 0px;"><a href="https://docs.google.com/presentation/d/1Osy7XQd9LuY7npicwK-r37cNOFUW0No3AwzEbEmRNqQ/present#slide=id.p"></a><a href="https://docs.google.com/presentation/d/1Osy7XQd9LuY7npicwK-r37cNOFUW0No3AwzEbEmRNqQ/present#slide=id.p">https://docs.google.com/presentation/d/1Osy7XQd9LuY7npicwK-r37cNOFUW0No3AwzEbEmRNqQ/present#slide=id.p</a> <strong>Russian language</strong> Slides for my presentation on Node.js and unittesting. Would be best if the reader woud understand the concepts of the unit testing (mocks, verification, structure, goal of unittesting, level of granularity, usual terminology), thought that’s not really required. </li>
</ol>
<div style="margin: 1.2em 0px !important;">
Happy to help if you have questions! </div>
<div style="margin: 1.2em 0px !important;">
Best,<br />Alex.</div>
</div>
</div>
Alexanderhttp://www.blogger.com/profile/10093762646999402082noreply@blogger.com0tag:blogger.com,1999:blog-5866514577340267046.post-74373042376042806112013-10-27T20:18:00.001+02:002013-10-27T20:18:17.265+02:00Node.js, elasticsearch, mognodb, ext.js and Heroku sample application - we have it as a work-in-progress<div dir="ltr" style="text-align: left;" trbidi="on">
<div class="markdown-here-wrapper" data-md-original="%3Cp%3EHello!%26nbsp%3B%3C%2Fp%3E%3Cp%3E%3Cbr%3E%3C%2Fp%3E%3Cp%3EWe%20have%20built%20a%20sample%20application%20to%20use%20as%20a%20base%20(archetype-like)%20for%20the%20forementioned%20stack.%20It%20is%20accessible%20on%20GitHub%20and%20we%20really%20welcoming%20everyone%20trying%20to%20interact%20with%20it%20somehow.%20Push%20it%2C%20copy%2C%20use%2C%20fork%2C%20augment%20-%20great.%20Comments%20and%20questions%3F%20Totally%20wonderful.%20Complaints%20and%20ideas%3F%20Great%20as%20well!%20We%20look%20forward%20to%20improving%20it.%26nbsp%3B%3C%2Fp%3E%3Cp%3E%3Cbr%3E%3C%2Fp%3E%3Cp%3EThe%20idea%20of%20the%20app%20is%20boring%20-%20it's%20CRUD%2BS(earch)%20app%20for%20bookshelf%20functionality.%20Nah%2C%20boring.%20Node.js%2C%20elasticsearch%2C%20mognodb%2C%20ext.js%20and%20Heroku%20sample%20application%3B%20it%20was%20written%20in%202%20days%20by%204%20people%20who%20have%20never%20used%20and%20even%20tried%20any%20of%20this%20tech%20before.%20This%20is%20a%20great%20illustration%20of%20quite%20a%20fast%20time-to-dev.%20The%20domain%20itself%20(books)%20is%20quite%20non-intrusive%2C%20which%20means%20you%20can%20play%20around%20with%20different%20components%20easily.%3C%2Fp%3E%3Cp%3E%3Cbr%3E%3C%2Fp%3E%3Cp%3EAs%20of%20now%2C%20here's%20what%20we%20have%3A%26nbsp%3B%3C%2Fp%3E%3Cp%3E%3Cbr%3E%3C%2Fp%3E%3Cp%3E1.%20Source%20codes%20are%20accessible%20on%26nbsp%3B%3Ca%20href%3D%22https%3A%2F%2Fgithub.com%2FLogicify%2Fnodejs-sample-task%22%3Ehttps%3A%2F%2Fgithub.com%2FLogicify%2Fnodejs-sample-task%3C%2Fa%3E%3C%2Fp%3E%3Cp%3E1.%20The%20app%20deployed%20to%26nbsp%3B%3Ca%20href%3D%22http%3A%2F%2Fnodejs-sample-task.logicify.com%2F%22%3Ehttp%3A%2F%2Fnodejs-sample-task.logicify.com%2F%3C%2Fa%3E%26nbsp%3B%20and%20visible%20in%20the%20Internet%3C%2Fp%3E%3Cp%3E1.%20It%20has%20all%20the%20stuff%20necessary%20for%20Heroku%20deployment.%26nbsp%3B%3C%2Fp%3E%3Cp%3E1.%20Exposes%20minimal%20architecture.%20From%20the%20point%20we've%20been%20working%20with%20this%2C%20we've%20came%20to%20way%20better%20way%20of%20handling%20the%20configuration%2C%20exceptions%2C%20logging%2C%20etc.%26nbsp%3B%3C%2Fp%3E%3Cp%3E1.%20It%20has%20around%20half%20of%20the%20testing%20facilities%20(supertest%2C%20mocha%2C%20jscoverage%2C%20chaijs)%20setup%2C%20but%20is%20missing%2C%20for%20instance%2C%20nice%20usage%20of%20Sinon.%3C%2Fp%3E%3Cp%3E1.%20Has%20some%20basic%20documentation.%26nbsp%3B%3C%2Fp%3E%3Cp%3E%3Cbr%3E%3C%2Fp%3E%3Cp%3EUpcoming%20plans%3A%26nbsp%3B%3C%2Fp%3E%3Cp%3E1.%20Add%20'proper'%20configuration%20handling%20(with%20several%20config%20files%20and%20env%20variable%20switching%20them)%3C%2Fp%3E%3Cp%3E1.%20Proper%20logger%20wrapper.%3C%2Fp%3E%3Cp%3E1.%20Improved%20testing%20-%20showcasing%20Sinon.js%20and%20some%20better%20assertions.%26nbsp%3B%3C%2Fp%3E%3Cp%3E1.%20Growing%20a%20little%20more%20functionality.%26nbsp%3B%3C%2Fp%3E%3Cp%3E%3Cbr%3E%3C%2Fp%3E%3Cp%3E%3Cbr%3E%3C%2Fp%3E%3Cp%3EThis%20demo%20was%20partly%20created%20as%20a%20Proof%20of%20Concept%20we've%20been%20doing%20for%20one%20of%20our%20customers%20back%20in%20May%2C%20and%20partly%20as%20a%20demo%20app%20for%202%20talks%20me%20and%20Pavel%20Knorr%20were%20having%20on%20the%20local%20Kherson%20it-talk%20meetup.%20Still%20has%20huge%20room%20for%20improvement%2C%20and%20that's%20what%20we'll%20try%20to%20do.%3C%2Fp%3E%3Cp%3E%3Cbr%3E%3C%2Fp%3E%3Cp%3EAlso%2C%20it%20was%20created%20by%20%5BLogicify%5D(http%3A%2F%2Flogicify.com)%20team%26nbsp%3B%3C%2Fp%3E%3Cp%3E%3Cbr%3E%3C%2Fp%3E%3Cp%3E**%5BADS%20MODE%20ON%5D**%3C%2Fp%3E%3Cp%3Ewe%20are%20doing%20great%20custom%20software%20development%20and%20services.%20You%20can%20reach%20me%20for%20any%20enquiries%20or%20use%20the%20website%20%3A)%3C%2Fp%3E%3Cp%3E**%5BADS%20MODE%20OFF%5D**%3C%2Fp%3E%3Cp%3E%3Cbr%3E%3C%2Fp%3E%3Cp%3E%2C%20and%20at%20Logicify%20we%20really%20have%20already%20used%20this%20project%20twice%20as%20an%20archetype%20-%20cloning%20it%2C%20fixing%20something%20in%20it%20and%20making%20it%20effectively%20a%20seed%20of%20the%20new%20project.%3C%2Fp%3E%3Cp%3E%3Cbr%3E%3C%2Fp%3E%3Cp%3ESo%2C%20if%20you'd%20like%20to%20interact%20with%20it%20-%20please%20do!%3Cbr%3E%3C%2Fp%3E%3Cp%3E%3Cbr%3E%3C%2Fp%3E%3Cp%3ECheers%2C%3C%2Fp%3E%3Cp%3EAlex.%3C%2Fp%3E" data-md-url="http://www.blogger.com/blogger.g?blogID=5866514577340267046#editor/target=post;postID=7437304237604280611" id="markdown-here-wrapper-421884">
<div style="margin: 1.2em 0px !important;">
Hello! </div>
<div style="margin: 1.2em 0px !important;">
We have built a sample application to use as a base (archetype-like) for the forementioned stack. It is accessible on GitHub and we really welcoming everyone trying to interact with it somehow. Push it, copy, use, fork, augment - great. Comments and questions? Totally wonderful. Complaints and ideas? Great as well! We look forward to improving it. </div>
<div style="margin: 1.2em 0px !important;">
The idea of the app is boring - it’s CRUD+S(earch) app for bookshelf functionality. Nah, boring. Node.js, elasticsearch, mognodb, ext.js and Heroku sample application; it was written in 2 days by 4 people who have never used and even tried any of this tech before. This is a great illustration of quite a fast time-to-dev. The domain itself (books) is quite non-intrusive, which means you can play around with different components easily.</div>
<div style="margin: 1.2em 0px !important;">
As of now, here’s what we have: </div>
<ol style="margin: 1.2em 0px; padding-left: 2em;">
<li style="margin: 0.5em 0px;">Source codes are accessible on <a href="https://github.com/Logicify/nodejs-sample-task"></a><a href="https://github.com/Logicify/nodejs-sample-task">https://github.com/Logicify/nodejs-sample-task</a></li>
<li style="margin: 0.5em 0px;">The app deployed to <a href="http://nodejs-sample-task.logicify.com/"></a><a href="http://nodejs-sample-task.logicify.com/">http://nodejs-sample-task.logicify.com/</a> and visible in the Internet</li>
<li style="margin: 0.5em 0px;">It has all the stuff necessary for Heroku deployment. </li>
<li style="margin: 0.5em 0px;">Exposes minimal architecture. From the point we’ve been working with this, we’ve came to way better way of handling the configuration, exceptions, logging, etc. </li>
<li style="margin: 0.5em 0px;">It has around half of the testing facilities (supertest, mocha, jscoverage, chaijs) setup, but is missing, for instance, nice usage of Sinon.</li>
<li style="margin: 0.5em 0px;">Has some basic documentation. </li>
</ol>
<div style="margin: 1.2em 0px !important;">
Upcoming plans: </div>
<ol style="margin: 1.2em 0px; padding-left: 2em;">
<li style="margin: 0.5em 0px;">Add ‘proper’ configuration handling (with several config files and env variable switching them)</li>
<li style="margin: 0.5em 0px;">Proper logger wrapper.</li>
<li style="margin: 0.5em 0px;">Improved testing - showcasing Sinon.js and some better assertions. </li>
<li style="margin: 0.5em 0px;">Growing a little more functionality. </li>
</ol>
<div style="margin: 1.2em 0px !important;">
This demo was partly created as a Proof of Concept we’ve been doing for one of our customers back in May, and partly as a demo app for 2 talks me and Pavel Knorr were having on the local Kherson it-talk meetup. Still has huge room for improvement, and that’s what we’ll try to do.</div>
<div style="margin: 1.2em 0px !important;">
Also, it was created by <a href="http://logicify.com/">Logicify</a> team </div>
<div style="margin: 1.2em 0px !important;">
<strong>[ADS MODE ON]</strong><br />we are doing great custom software development and services. You can reach me for any enquiries or use the website :)<br /><strong>[ADS MODE OFF]</strong></div>
<div style="margin: 1.2em 0px !important;">
, and at Logicify we really have already used this project twice as an archetype - cloning it, fixing something in it and making it effectively a seed of the new project.</div>
<div style="margin: 1.2em 0px !important;">
So, if you’d like to interact with it - please do!</div>
<div style="margin: 1.2em 0px !important;">
Cheers,<br />Alex.</div>
</div>
</div>
Alexanderhttp://www.blogger.com/profile/10093762646999402082noreply@blogger.com2tag:blogger.com,1999:blog-5866514577340267046.post-73435212910223120002013-10-18T11:10:00.001+03:002013-10-27T20:54:17.971+02:00Node.js express middleware: beware of reading data before the bodyParser()!<div dir="ltr" style="text-align: left;" trbidi="on">
<div class="markdown-here-wrapper" data-md-original="%3Cp%3EFound%20that%20yesterday%2C%20as%20a%20part%20of%20implementation%20of%20HMAC-like%20functionality.%20So%2C%20what%20we%20did%3A%26nbsp%3B%3C%2Fp%3E%3Cp%3E%3Cbr%3E%3C%2Fp%3E%3Cp%3E%60%60%60javascript%3C%2Fp%3E%3Cp%3E%2F*%3C%2Fp%3E%3Cp%3ETHIS%20IS%20A%20CODE%20WHICH%20IS%20____NOT____%20WORKING!%20DON'T%20USE%20IT%20PLEASE!%3C%2Fp%3E%3Cp%3E*%2F%3C%2Fp%3E%3Cp%3Eapp.use(function%20(req%2C%20res%2C%20next)%20%7B%3C%2Fp%3E%3Cp%3E%26nbsp%3B%20%26nbsp%3B%20var%20headerValue%20%3D%20req.header(secureAPIHeader)%3B%3C%2Fp%3E%3Cp%3E%26nbsp%3B%20%26nbsp%3B%20req.hasher%20%3D%20crypto.createHmac(%22sha256%22%2C%20config.secretAdminAPIKey)%3B%3C%2Fp%3E%3Cp%3E%26nbsp%3B%20%26nbsp%3B%20req.setEncoding('utf8')%3B%3C%2Fp%3E%3Cp%3E%26nbsp%3B%20%26nbsp%3B%20req.on('data'%2C%20function%20(chunk)%20%7B%3C%2Fp%3E%3Cp%3E%26nbsp%3B%20%26nbsp%3B%20%26nbsp%3B%20%26nbsp%3B%20req.hasher.update(chunk)%3B%3C%2Fp%3E%3Cp%3E%26nbsp%3B%20%26nbsp%3B%20%7D)%3B%3C%2Fp%3E%3Cp%3E%26nbsp%3B%20%26nbsp%3B%20req.on('end'%2C%20function%20()%20%7B%3C%2Fp%3E%3Cp%3E%26nbsp%3B%20%26nbsp%3B%20%26nbsp%3B%20%26nbsp%3B%20var%20hash%20%3D%20req.hasher.digest('hex')%3B%3C%2Fp%3E%3Cp%3E%26nbsp%3B%20%26nbsp%3B%20%26nbsp%3B%20%26nbsp%3B%20if%20(hash%20!%3D%20headerValue)%20%7B%3C%2Fp%3E%3Cp%3E%26nbsp%3B%20%26nbsp%3B%20%26nbsp%3B%20%26nbsp%3B%20%26nbsp%3B%20%26nbsp%3B%20log.err(util.format(%22Received%20wrong%20Admin%20request%2C%20hashes%20do%20not%20match.%20Received%20hash%20%25s%20want%20hash%20%25s%22%2C%20headerValue%2C%20hash))%3B%3C%2Fp%3E%3Cp%3E%26nbsp%3B%20%26nbsp%3B%20%26nbsp%3B%20%26nbsp%3B%20%26nbsp%3B%20%26nbsp%3B%20res.json(403%2C%20%7Bmessage%3A%20%22Not%20authorized%22%7D)%3B%3C%2Fp%3E%3Cp%3E%26nbsp%3B%20%26nbsp%3B%20%26nbsp%3B%20%26nbsp%3B%20%7D%20else%20%7B%3C%2Fp%3E%3Cp%3E%26nbsp%3B%20%26nbsp%3B%20%26nbsp%3B%20%26nbsp%3B%20%26nbsp%3B%20%26nbsp%3B%20log.warn(%22Received%20admin%20request%20for%20url%20%22%20%2B%20req.url)%3B%3C%2Fp%3E%3Cp%3E%26nbsp%3B%20%26nbsp%3B%20%26nbsp%3B%20%26nbsp%3B%20%26nbsp%3B%20%26nbsp%3B%20req.isSuperSecure%20%3D%20true%3B%3C%2Fp%3E%3Cp%3E%26nbsp%3B%20%26nbsp%3B%20%26nbsp%3B%20%26nbsp%3B%20%26nbsp%3B%20%26nbsp%3B%20next()%3B%3C%2Fp%3E%3Cp%3E%26nbsp%3B%20%26nbsp%3B%20%26nbsp%3B%20%26nbsp%3B%20%7D%3C%2Fp%3E%3Cp%3E%26nbsp%3B%20%26nbsp%3B%20%7D)%3B%3C%2Fp%3E%3Cp%3E%7D)%3B%3C%2Fp%3E%3Cp%3E%60%60%60%3Cbr%3E%3Cbr%3E%3C%2Fp%3E%3Cp%3EIt%20exposed%20quite%20weird%20(not%20really)%20behavior.%20When%20the%20request%20with%20the%20wrong%20HMAC%20was%20coming%20in%2C%20the%20server%20gave%20away%20the%20correct%20403%20error.%20However%2C%20if%20the%20HMAC%20was%20correct%2C%20the%20server%20would%20never%20return%20from%20call%20chain.%26nbsp%3B%3C%2Fp%3E%3Cp%3E%3Cbr%3E%3C%2Fp%3E%3Cp%3EFurther%20investigation%20showed%20that%20it%20was%20quite%20simple.%20Since%20we%20have%20finished%20reading%20all%20the%20data%20from%20stream%20(and%20successfully%20received%20'end'%20event)%2C%20the%20underlying%20%60bodyParser%60%20was%20forever%20blocked%20on%20'end'%20event%20which%20would%20never%20be%20issued!%20Actually%2C%20%60bodyParser%60%20was%20only%20subscribing%20to%20this%20event%20when%20the%20whole%20data%20bunch%20was%20read.%26nbsp%3B%3C%2Fp%3E%3Cp%3E%3Cbr%3E%3C%2Fp%3E%3Cp%3EWe%20didn't%20really%20want%20to%20divert%20from%20streaming%20nature%20of%20the%20node.js%20crypto%20hasher%20and%20read%20all%20data%20into%20a%20huge%20string.%20So%20this%20middleware%20came%20into%20play%3A%26nbsp%3B%3C%2Fp%3E%3Cp%3E%3Cbr%3E%3C%2Fp%3E%3Cp%3E%60%60%60javascript%3C%2Fp%3E%3Cp%3E%2F*%3C%2Fp%3E%3Cp%3EA%20correct%20version.%20The%20underlying%20data%20sourcers%20are%20not%20blocked.%3C%2Fp%3E%3Cp%3E*%2F%3C%2Fp%3E%3Cp%3Eapp.use(function%20(req%2C%20res%2C%20next)%20%7B%3C%2Fp%3E%3Cp%3E%26nbsp%3B%20%26nbsp%3B%20var%20headerValue%20%3D%20req.header(secureAPIHeader)%3B%3C%2Fp%3E%3Cp%3E%26nbsp%3B%20%26nbsp%3B%20req.hasher%20%3D%20crypto.createHmac(%22sha256%22%2C%20config.secretAdminAPIKey)%3B%3C%2Fp%3E%3Cp%3E%26nbsp%3B%20%26nbsp%3B%20req.setEncoding('utf8')%3B%3C%2Fp%3E%3Cp%3E%26nbsp%3B%20%26nbsp%3B%20req.on('data'%2C%20function%20(chunk)%20%7B%3C%2Fp%3E%3Cp%3E%26nbsp%3B%20%26nbsp%3B%20%26nbsp%3B%20%26nbsp%3B%20req.hasher.update(chunk)%3B%3C%2Fp%3E%3Cp%3E%26nbsp%3B%20%26nbsp%3B%20%7D)%3B%3C%2Fp%3E%3Cp%3E%26nbsp%3B%20%26nbsp%3B%20req.on('end'%2C%20function%20()%20%7B%3C%2Fp%3E%3Cp%3E%26nbsp%3B%20%26nbsp%3B%20%26nbsp%3B%20%26nbsp%3B%20var%20hash%20%3D%20req.hasher.digest('hex')%3B%3C%2Fp%3E%3Cp%3E%26nbsp%3B%20%26nbsp%3B%20%26nbsp%3B%20%26nbsp%3B%20if%20(hash%20!%3D%20headerValue)%20%7B%3C%2Fp%3E%3Cp%3E%26nbsp%3B%20%26nbsp%3B%20%26nbsp%3B%20%26nbsp%3B%20%26nbsp%3B%20%26nbsp%3B%20log.err(util.format(%22Received%20wrong%20Admin%20request%2C%20hashes%20do%20not%20match.%20Received%20hash%20%25s%20want%20hash%20%25s%22%2C%20headerValue%2C%20hash))%3B%3C%2Fp%3E%3Cp%3E%26nbsp%3B%20%26nbsp%3B%20%26nbsp%3B%20%26nbsp%3B%20%26nbsp%3B%20%26nbsp%3B%20res.json(403%2C%20%7Bmessage%3A%20%22Not%20authorized%22%7D)%3B%3C%2Fp%3E%3Cp%3E%26nbsp%3B%20%26nbsp%3B%20%26nbsp%3B%20%26nbsp%3B%20%7D%20else%20%7B%3C%2Fp%3E%3Cp%3E%26nbsp%3B%20%26nbsp%3B%20%26nbsp%3B%20%26nbsp%3B%20%26nbsp%3B%20%26nbsp%3B%20log.warn(%22Received%20admin%20request%20for%20url%20%22%20%2B%20req.url)%3B%3C%2Fp%3E%3Cp%3E%26nbsp%3B%20%26nbsp%3B%20%26nbsp%3B%20%26nbsp%3B%20%26nbsp%3B%20%26nbsp%3B%20req.isSuperSecure%20%3D%20true%3B%3C%2Fp%3E%3Cp%3E%26nbsp%3B%20%26nbsp%3B%20%26nbsp%3B%20%26nbsp%3B%20%7D%3C%2Fp%3E%3Cp%3E%26nbsp%3B%20%26nbsp%3B%20%7D)%3B%3C%2Fp%3E%3Cp%3E%26nbsp%3B%20%26nbsp%3B%20%2F%2F%20This%20is%20the%20only%20difference%20-%20we%20execute%20middlewares%20in%20parallel!%26nbsp%3B%3C%2Fp%3E%3Cp%3E%26nbsp%3B%20%26nbsp%3B%20%2F%2F%20%3D%26gt%3B%26nbsp%3B%3C%2Fp%3E%3Cp%3E%26nbsp%3B%20%26nbsp%3B%20next()%3B%3C%2Fp%3E%3Cp%3E%7D)%3B%3C%2Fp%3E%3Cp%3E%60%60%60%3C%2Fp%3E%3Cp%3E%3Cbr%3E%3C%2Fp%3E%3Cp%3ETrick%20here%20is%20that%20we%20pass%20execution%20to%20the%20underlying%20bodyParser%20straight%20away.%20And%2C%20when%20bodyParser%20receives%20data%20so%20do%20we%20-%20there%20are%202%20listeners%20for%20%60data%60%20and%20%60end%60%20events%20here.%20There%20is%20an%20issue%20with%20this%20solution%2C%20though.%20We%20are%20not%20strongly%20coupling%20the%20moments%20when%20hmac%20becomes%20available%20in%20request%2C%20and%20the%20processing%20is%20done.%20%60bodyParser%60%20does%20this%20for%20us.%26nbsp%3B%3C%2Fp%3E%3Cp%3E%3Cbr%3E%3C%2Fp%3E%3Cp%3EMoreover%2C%20got%20an%20extra-quick%20reaction%20by%20the%20express%20team%2C%20and%20now%20there's%20a%20%60verify%60%20method%20(in%20pull%20request%20as%20of%202013-10-18)%2C%20which%20does%20exactly%20what%20we%20do%2C%20but%20w%2Fout%20streaming%20(for%20JSON%20only)%2C%20which%20should%20be%20good%20for%2090%25%20users.%20Here's%20discussion%20link%3A%26nbsp%3B%3Ca%20href%3D%22https%3A%2F%2Fgithub.com%2Fvisionmedia%2Fexpress%2Fissues%2F897%23issuecomment-26575496%22%3Ehttps%3A%2F%2Fgithub.com%2Fvisionmedia%2Fexpress%2Fissues%2F897%23issuecomment-26575496%3C%2Fa%3E%3C%2Fp%3E%3Cp%3E%3Cbr%3E%3C%2Fp%3E%3Cp%3E%3Cbr%3E%3C%2Fp%3E%3Cp%3EThanks!%26nbsp%3B%3C%2Fp%3E" data-md-url="http://www.blogger.com/blogger.g?blogID=5866514577340267046#editor/target=post;postID=7343521291022312000" id="markdown-here-wrapper-916669">
<div style="margin: 1.2em 0px !important;">
Found that yesterday, as a part of implementation of HMAC-like functionality. So, what we did: </div>
<pre style="font-family: Consolas, Inconsolata, Courier, monospace; font-size: 0.85em; font-size: 1em; line-height: 1.2em; margin: 1.2em 0px;"><code class="language-javascript" style="background-color: #f8f8f8; background-color: ghostwhite; background-position: initial initial; background-repeat: initial initial; border-bottom-left-radius: 3px; border-bottom-left-radius: 3px; border-bottom-right-radius: 3px; border-bottom-right-radius: 3px; border-top-left-radius: 3px; border-top-left-radius: 3px; border-top-right-radius: 3px; border-top-right-radius: 3px; border: 1px solid rgb(204, 204, 204); border: 1px solid rgb(234, 234, 234); color: #333333; display: block; display: inline; font-family: Consolas, Inconsolata, Courier, monospace; font-size: 0.85em; margin: 0px 0.15em; overflow: auto; padding: 0.5em 0.7em; padding: 0.5em; padding: 0px 0.3em; white-space: pre-wrap; white-space: pre;"><span class="comment" style="color: #999988; font-style: italic;">/*
THIS IS A CODE WHICH IS ____NOT____ WORKING! DON'T USE IT PLEASE!
*/</span>
app.use(<span class="function"><span class="keyword" style="color: #333333; font-weight: bold;">function</span> <span class="params">(req, res, next)</span> {</span>
<span class="keyword" style="color: #333333; font-weight: bold;">var</span> headerValue = req.header(secureAPIHeader);
req.hasher = crypto.createHmac(<span class="string" style="color: #dd1144;">"sha256"</span>, config.secretAdminAPIKey);
req.setEncoding(<span class="string" style="color: #dd1144;">'utf8'</span>);
req.on(<span class="string" style="color: #dd1144;">'data'</span>, <span class="function"><span class="keyword" style="color: #333333; font-weight: bold;">function</span> <span class="params">(chunk)</span> {</span>
req.hasher.update(chunk);
});
req.on(<span class="string" style="color: #dd1144;">'end'</span>, <span class="function"><span class="keyword" style="color: #333333; font-weight: bold;">function</span> <span class="params">()</span> {</span>
<span class="keyword" style="color: #333333; font-weight: bold;">var</span> hash = req.hasher.digest(<span class="string" style="color: #dd1144;">'hex'</span>);
<span class="keyword" style="color: #333333; font-weight: bold;">if</span> (hash != headerValue) {
log.err(util.format(<span class="string" style="color: #dd1144;">"Received wrong Admin request, hashes do not match. Received hash %s want hash %s"</span>, headerValue, hash));
res.json(<span class="number" style="color: #009999;">403</span>, {message: <span class="string" style="color: #dd1144;">"Not authorized"</span>});
} <span class="keyword" style="color: #333333; font-weight: bold;">else</span> {
log.warn(<span class="string" style="color: #dd1144;">"Received admin request for url "</span> + req.url);
req.isSuperSecure = <span class="literal">true</span>;
next();
}
});
});</code></pre>
<div style="margin: 1.2em 0px !important;">
It exposed quite weird (not really) behavior. When the request with the wrong HMAC was coming in, the server gave away the correct 403 error. However, if the HMAC was correct, the server would never return from call chain. </div>
<div style="margin: 1.2em 0px !important;">
Further investigation showed that it was quite simple. Since we have finished reading all the data from stream (and successfully received ‘end’ event), the underlying <code style="background-color: #f8f8f8; border-bottom-left-radius: 3px; border-bottom-right-radius: 3px; border-top-left-radius: 3px; border-top-right-radius: 3px; border: 1px solid rgb(234, 234, 234); display: inline; font-family: Consolas, Inconsolata, Courier, monospace; font-size: 0.85em; margin: 0px 0.15em; padding: 0px 0.3em; white-space: pre-wrap;">bodyParser</code> was forever blocked on ‘end’ event which would never be issued! Actually, <code style="background-color: #f8f8f8; border-bottom-left-radius: 3px; border-bottom-right-radius: 3px; border-top-left-radius: 3px; border-top-right-radius: 3px; border: 1px solid rgb(234, 234, 234); display: inline; font-family: Consolas, Inconsolata, Courier, monospace; font-size: 0.85em; margin: 0px 0.15em; padding: 0px 0.3em; white-space: pre-wrap;">bodyParser</code> was only subscribing to this event when the whole data bunch was read. </div>
<div style="margin: 1.2em 0px !important;">
We didn’t really want to divert from streaming nature of the node.js crypto hasher and read all data into a huge string. So this middleware came into play: </div>
<pre style="font-family: Consolas, Inconsolata, Courier, monospace; font-size: 0.85em; font-size: 1em; line-height: 1.2em; margin: 1.2em 0px;"><code class="language-javascript" style="background-color: #f8f8f8; background-color: ghostwhite; background-position: initial initial; background-repeat: initial initial; border-bottom-left-radius: 3px; border-bottom-left-radius: 3px; border-bottom-right-radius: 3px; border-bottom-right-radius: 3px; border-top-left-radius: 3px; border-top-left-radius: 3px; border-top-right-radius: 3px; border-top-right-radius: 3px; border: 1px solid rgb(204, 204, 204); border: 1px solid rgb(234, 234, 234); color: #333333; display: block; display: inline; font-family: Consolas, Inconsolata, Courier, monospace; font-size: 0.85em; margin: 0px 0.15em; overflow: auto; padding: 0.5em 0.7em; padding: 0.5em; padding: 0px 0.3em; white-space: pre-wrap; white-space: pre;"><span class="comment" style="color: #999988; font-style: italic;">/*
A correct version. The underlying data sourcers are not blocked.
*/</span>
app.use(<span class="function"><span class="keyword" style="color: #333333; font-weight: bold;">function</span> <span class="params">(req, res, next)</span> {</span>
<span class="keyword" style="color: #333333; font-weight: bold;">var</span> headerValue = req.header(secureAPIHeader);
req.hasher = crypto.createHmac(<span class="string" style="color: #dd1144;">"sha256"</span>, config.secretAdminAPIKey);
req.setEncoding(<span class="string" style="color: #dd1144;">'utf8'</span>);
req.on(<span class="string" style="color: #dd1144;">'data'</span>, <span class="function"><span class="keyword" style="color: #333333; font-weight: bold;">function</span> <span class="params">(chunk)</span> {</span>
req.hasher.update(chunk);
});
req.on(<span class="string" style="color: #dd1144;">'end'</span>, <span class="function"><span class="keyword" style="color: #333333; font-weight: bold;">function</span> <span class="params">()</span> {</span>
<span class="keyword" style="color: #333333; font-weight: bold;">var</span> hash = req.hasher.digest(<span class="string" style="color: #dd1144;">'hex'</span>);
<span class="keyword" style="color: #333333; font-weight: bold;">if</span> (hash != headerValue) {
log.err(util.format(<span class="string" style="color: #dd1144;">"Received wrong Admin request, hashes do not match. Received hash %s want hash %s"</span>, headerValue, hash));
res.json(<span class="number" style="color: #009999;">403</span>, {message: <span class="string" style="color: #dd1144;">"Not authorized"</span>});
} <span class="keyword" style="color: #333333; font-weight: bold;">else</span> {
log.warn(<span class="string" style="color: #dd1144;">"Received admin request for url "</span> + req.url);
req.isSuperSecure = <span class="literal">true</span>;
}
});
<span class="comment" style="color: #999988; font-style: italic;">// This is the only difference - we execute middlewares in parallel! </span>
<span class="comment" style="color: #999988; font-style: italic;">// => </span>
next();
});</code></pre>
<div style="margin: 1.2em 0px !important;">
Trick here is that we pass execution to the underlying bodyParser straight away. And, when bodyParser receives data so do we - there are 2 listeners for <code style="background-color: #f8f8f8; border-bottom-left-radius: 3px; border-bottom-right-radius: 3px; border-top-left-radius: 3px; border-top-right-radius: 3px; border: 1px solid rgb(234, 234, 234); display: inline; font-family: Consolas, Inconsolata, Courier, monospace; font-size: 0.85em; margin: 0px 0.15em; padding: 0px 0.3em; white-space: pre-wrap;">data</code> and <code style="background-color: #f8f8f8; border-bottom-left-radius: 3px; border-bottom-right-radius: 3px; border-top-left-radius: 3px; border-top-right-radius: 3px; border: 1px solid rgb(234, 234, 234); display: inline; font-family: Consolas, Inconsolata, Courier, monospace; font-size: 0.85em; margin: 0px 0.15em; padding: 0px 0.3em; white-space: pre-wrap;">end</code> events here. There is an issue with this solution, though. We are not strongly coupling the moments when hmac becomes available in request, and the processing is done. <code style="background-color: #f8f8f8; border-bottom-left-radius: 3px; border-bottom-right-radius: 3px; border-top-left-radius: 3px; border-top-right-radius: 3px; border: 1px solid rgb(234, 234, 234); display: inline; font-family: Consolas, Inconsolata, Courier, monospace; font-size: 0.85em; margin: 0px 0.15em; padding: 0px 0.3em; white-space: pre-wrap;">bodyParser</code> does this for us. </div>
<div style="margin: 1.2em 0px !important;">
Moreover, got an extra-quick reaction by the express team, and now there’s a <code style="background-color: #f8f8f8; border-bottom-left-radius: 3px; border-bottom-right-radius: 3px; border-top-left-radius: 3px; border-top-right-radius: 3px; border: 1px solid rgb(234, 234, 234); display: inline; font-family: Consolas, Inconsolata, Courier, monospace; font-size: 0.85em; margin: 0px 0.15em; padding: 0px 0.3em; white-space: pre-wrap;">verify</code> method (in pull request as of 2013-10-18), which does exactly what we do, but w/out streaming (for JSON only), which should be good for 90% users. Here’s discussion link: <a href="https://github.com/visionmedia/express/issues/897#issuecomment-26575496"></a><a href="https://github.com/visionmedia/express/issues/897#issuecomment-26575496">https://github.com/visionmedia/express/issues/897#issuecomment-26575496</a></div>
<div style="margin: 1.2em 0px !important;">
Thanks! </div>
</div>
</div>
Alexanderhttp://www.blogger.com/profile/10093762646999402082noreply@blogger.com0tag:blogger.com,1999:blog-5866514577340267046.post-9081308695586218182013-10-14T21:56:00.001+03:002013-10-14T21:56:13.588+03:00JMeter not sending body with the PUT method<div dir="ltr" style="text-align: left;" trbidi="on">
<div class="markdown-here-wrapper" data-md-original="%3Cp%3ENoticed%20very%2C%20very%20strange%20behavior.%20When%20we%20issue%20a%20%60PUT%60%20request%20with%20jMeter's%20HTTP%20Sampler%2C%20it%20totally%20ignores%20what%20we%20have%20in%20Post%20Data%20or%20in%20the%20Raw%20Post%20Data%20section.%26nbsp%3B%3C%2Fp%3E%3Cp%3E%3Cbr%3E%3C%2Fp%3E%3Cp%3EThat's%20kind%20of%20crazy%2C%20since%20I%20would%20expect%20%60PUT%60%20method%20to%20be%20an%20HTTP%20mutator%20as%20well%2C%20and%20where's%20the%20state%20if%20we%20don't%20send%20it%3F%3C%2Fp%3E%3Cp%3E%3Cbr%3E%3C%2Fp%3E%3Cp%3EHowever%20HTTP%20is%20OK%2C%20it's%20rather%20issues%20of%20the%20jMeter%20or%20underlying%20libraries.%20In%20order%20to%20make%20%60PUT%60%20method%20send%20the%20%60POST%60%20body%2C%20one%20could%20simply%20**set%20the%20encoding%20to%20UTF-8%20(that's%20the%20box%20exactly%20after%20the%20method%20dropdown**.%20And%20it%20works.%20A%20kind%20of%20magic%2C%20but%20ate%20another%2030%20mins%20of%20my%20time.%26nbsp%3B%3C%2Fp%3E%3Cp%3E%3Cbr%3E%3C%2Fp%3E%3Cp%3EI%20had%20that%20issue%20on%20jMeter%202.9%2C%20and%20it%20seems%20to%20be%20quite%20common%20since%20that's%20the%20%5Blink%5D(%3Ca%20href%3D%22http%3A%2F%2Fjmeter.512774.n5.nabble.com%2FSending-Body-with-PUT-td5473957.html%22%3Ehttp%3A%2F%2Fjmeter.512774.n5.nabble.com%2FSending-Body-with-PUT-td5473957.html%3C%2Fa%3E)%20where%20I%20have%20found%20the%20solution.%26nbsp%3B%3C%2Fp%3E" data-md-url="http://www.blogger.com/blogger.g?blogID=5866514577340267046#editor/target=post;postID=908130869558621818" id="markdown-here-wrapper-991843">
<div style="margin: 1.2em 0px !important;">
Noticed very, very strange behavior. When we issue a <code style="background-color: #f8f8f8; border-bottom-left-radius: 3px; border-bottom-right-radius: 3px; border-top-left-radius: 3px; border-top-right-radius: 3px; border: 1px solid rgb(234, 234, 234); display: inline; font-family: Consolas, Inconsolata, Courier, monospace; font-size: 0.85em; margin: 0px 0.15em; padding: 0px 0.3em; white-space: pre-wrap;">PUT</code> request with jMeter’s HTTP Sampler, it totally ignores what we have in Post Data or in the Raw Post Data section. </div>
<div style="margin: 1.2em 0px !important;">
That’s kind of crazy, since I would expect <code style="background-color: #f8f8f8; border-bottom-left-radius: 3px; border-bottom-right-radius: 3px; border-top-left-radius: 3px; border-top-right-radius: 3px; border: 1px solid rgb(234, 234, 234); display: inline; font-family: Consolas, Inconsolata, Courier, monospace; font-size: 0.85em; margin: 0px 0.15em; padding: 0px 0.3em; white-space: pre-wrap;">PUT</code> method to be an HTTP mutator as well, and where’s the state if we don’t send it?</div>
<div style="margin: 1.2em 0px !important;">
However HTTP is OK, it’s rather issues of the jMeter or underlying libraries. In order to make <code style="background-color: #f8f8f8; border-bottom-left-radius: 3px; border-bottom-right-radius: 3px; border-top-left-radius: 3px; border-top-right-radius: 3px; border: 1px solid rgb(234, 234, 234); display: inline; font-family: Consolas, Inconsolata, Courier, monospace; font-size: 0.85em; margin: 0px 0.15em; padding: 0px 0.3em; white-space: pre-wrap;">PUT</code> method send the <code style="background-color: #f8f8f8; border-bottom-left-radius: 3px; border-bottom-right-radius: 3px; border-top-left-radius: 3px; border-top-right-radius: 3px; border: 1px solid rgb(234, 234, 234); display: inline; font-family: Consolas, Inconsolata, Courier, monospace; font-size: 0.85em; margin: 0px 0.15em; padding: 0px 0.3em; white-space: pre-wrap;">POST</code> body, one could simply <strong>set the encoding to UTF-8 (that’s the box exactly after the method dropdown</strong>. And it works. A kind of magic, but ate another 30 mins of my time. </div>
<div style="margin: 1.2em 0px !important;">
I had that issue on jMeter 2.9, and it seems to be quite common since that’s the <a href="http://jmeter.512774.n5.nabble.com/Sending-Body-with-PUT-td5473957.html">link</a> where I have found the solution. </div>
</div>
</div>
Alexanderhttp://www.blogger.com/profile/10093762646999402082noreply@blogger.com1tag:blogger.com,1999:blog-5866514577340267046.post-12417562052951241472013-10-09T20:57:00.001+03:002013-10-09T21:20:44.191+03:00Chaining calls with Underscore.js<div dir="ltr" style="text-align: left;" trbidi="on">
<div class="markdown-here-wrapper" data-md-original="%3Cp%3EI%20have%20came%20underscore%20(%3Ca%20href%3D%22http%3A%2F%2Funderscorejs.org%2F%22%3Ehttp%3A%2F%2Funderscorejs.org%2F%3C%2Fa%3E)%20--%20a%20wonderful%20collection%20of%20javascript%20functions%20making%20one's%20life%20easier%20--%20a%20while%20ago.%3C%2Fp%3E%3Cp%3E%3Cbr%3E%3C%2Fp%3E%3Cp%3EHowever%2C%20I%20have%20only%20recently%20found%20out%20that%20underscore.js%20has%20a%20beautiful%20interface%20of%20chaining.%20The%20samples%20below%20are%20quite%20self-descriptive%20for%20anyone%20familiar%20with%20javascipt.%20But%20anyway%2C%20idea%20is%20that%20with%20chaining%2C%20underscore%20would%20automatically%20pass%20the%20result%20of%20the%20previous%20operation%20to%20the%20next%20one.%3C%2Fp%3E%3Cp%3E%3Cbr%3E%3C%2Fp%3E%3Cp%3EThat's%20how%20the%20work%20looks%20w%2Fout%20chaining%3A%3C%2Fp%3E%3Cp%3E%60%60%60javascript%3C%2Fp%3E%3Cp%3Evar%20someData%20%3D%20%5B1%2C4%2C2%2C4%2C5%2C6%5D%3B%3C%2Fp%3E%3Cp%3Evar%20results%20%3D%20_.map(%3C%2Fp%3E%3Cp%3E%26nbsp%3B%20%26nbsp%3B_.filter(%3C%2Fp%3E%3Cp%3E%26nbsp%3B%20%26nbsp%3B%20%26nbsp%3B%20_.sortBy(someData%2C%20_.identity)%2C%3C%2Fp%3E%3Cp%3E%26nbsp%3B%20%26nbsp%3B%20%26nbsp%3B%20function(a)%20%7Breturn%20a%26gt%3B3%7D)%2C%3C%2Fp%3E%3Cp%3E%26nbsp%3B%20%26nbsp%3Bfunction(m)%20%7Breturn%20m*m%7D%3C%2Fp%3E%3Cp%3E)%3B%3C%2Fp%3E%3Cp%3E%2F%2Foutputs%26nbsp%3B%5B16%2C%2016%2C%2025%2C%2036%5D%3C%2Fp%3E%3Cp%3E%60%60%60%3C%2Fp%3E%3Cp%3E%3Cbr%3E%3C%2Fp%3E%3Cp%3Eand%20that's%20how%20it%20looks%20like%20when%20we%20use%20method%20chaining%3A%3C%2Fp%3E%3Cp%3E%60%60%60javascript%3C%2Fp%3E%3Cp%3Evar%20someData%20%3D%20%5B1%2C4%2C2%2C4%2C5%2C6%5D%3B%3C%2Fp%3E%3Cp%3Evar%20results%20%3D%20_.chain(someData)%3C%2Fp%3E%3Cp%3E%26nbsp%3B%20%26nbsp%3B.sortBy(_.identity)%3C%2Fp%3E%3Cp%3E%26nbsp%3B%20%26nbsp%3B.filter(function(a)%7Breturn%20a%26gt%3B3%7D)%3C%2Fp%3E%3Cp%3E%26nbsp%3B%20%26nbsp%3B.map(function(m)%7Breturn%20m*m%7D)%3C%2Fp%3E%3Cp%3E%26nbsp%3B%20%26nbsp%3B.value()%3B%20%2F%2F%20that's%20the%20piece%20which%20'executes'%20the%20chain%3C%2Fp%3E%3Cp%3E%2F%2Foutputs%26nbsp%3B%5B16%2C%2016%2C%2025%2C%2036%5D%3C%2Fp%3E%3Cdiv%3E%60%60%60%3C%2Fdiv%3E%3Cp%3E%3Cbr%3E%3C%2Fp%3E%3Cp%3EYou%20judge%20which%20one%20is%20better!%3C%2Fp%3E" data-md-url="http://www.blogger.com/blogger.g?blogID=5866514577340267046#editor/target=post;postID=1241756205295124147;onPublishedMenu=allposts;onClosedMenu=allposts;postNum=0;src=link" id="markdown-here-wrapper-646143">
<div style="margin: 1.2em 0px !important;">
I have came across underscore (<a href="http://underscorejs.org/"></a><a href="http://underscorejs.org/">http://underscorejs.org/</a>) — a wonderful collection of javascript functions making one’s life easier — a while ago.</div>
<div style="margin: 1.2em 0px !important;">
However, I have only recently found out that underscore.js has a beautiful interface of chaining. The samples below are quite self-descriptive for anyone familiar with javascipt. But anyway, idea is that with chaining, underscore would automatically pass the result of the previous operation to the next one.</div>
<div style="margin: 1.2em 0px !important;">
That’s how the work looks w/out chaining:</div>
<pre style="font-family: Consolas, Inconsolata, Courier, monospace; font-size: 0.85em; font-size: 1em; line-height: 1.2em; margin: 1.2em 0px;"><code class="language-javascript" style="background-color: #f8f8f8; background-color: ghostwhite; background-position: initial initial; background-repeat: initial initial; border-bottom-left-radius: 3px; border-bottom-left-radius: 3px; border-bottom-right-radius: 3px; border-bottom-right-radius: 3px; border-top-left-radius: 3px; border-top-left-radius: 3px; border-top-right-radius: 3px; border-top-right-radius: 3px; border: 1px solid rgb(204, 204, 204); border: 1px solid rgb(234, 234, 234); color: #333333; display: block; display: inline; font-family: Consolas, Inconsolata, Courier, monospace; font-size: 0.85em; margin: 0px 0.15em; overflow: auto; padding: 0.5em 0.7em; padding: 0.5em; padding: 0px 0.3em; white-space: pre-wrap; white-space: pre;"><span class="keyword" style="color: #333333; font-weight: bold;">var</span> someData = [<span class="number" style="color: #009999;">1</span>,<span class="number" style="color: #009999;">4</span>,<span class="number" style="color: #009999;">2</span>,<span class="number" style="color: #009999;">4</span>,<span class="number" style="color: #009999;">5</span>,<span class="number" style="color: #009999;">6</span>];
<span class="keyword" style="color: #333333; font-weight: bold;">var</span> results = _.map(
_.filter(
_.sortBy(someData, _.identity),
<span class="keyword" style="color: #333333; font-weight: bold;">function</span>(a) {<span class="keyword" style="color: #333333; font-weight: bold;">return</span> a><span class="number" style="color: #009999;">3</span>}),
<span class="keyword" style="color: #333333; font-weight: bold;">function</span>(m) {<span class="keyword" style="color: #333333; font-weight: bold;">return</span> m*m}
);
<span class="comment" style="color: #999988; font-style: italic;">//outputs [16, 16, 25, 36]</span></code></pre>
<div style="margin: 1.2em 0px !important;">
and that’s how it looks like when we use method chaining:</div>
<pre style="font-family: Consolas, Inconsolata, Courier, monospace; font-size: 0.85em; font-size: 1em; line-height: 1.2em; margin: 1.2em 0px;"><code class="language-javascript" style="background-color: #f8f8f8; background-color: ghostwhite; background-position: initial initial; background-repeat: initial initial; border-bottom-left-radius: 3px; border-bottom-left-radius: 3px; border-bottom-right-radius: 3px; border-bottom-right-radius: 3px; border-top-left-radius: 3px; border-top-left-radius: 3px; border-top-right-radius: 3px; border-top-right-radius: 3px; border: 1px solid rgb(204, 204, 204); border: 1px solid rgb(234, 234, 234); color: #333333; display: block; display: inline; font-family: Consolas, Inconsolata, Courier, monospace; font-size: 0.85em; margin: 0px 0.15em; overflow: auto; padding: 0.5em 0.7em; padding: 0.5em; padding: 0px 0.3em; white-space: pre-wrap; white-space: pre;"><span class="keyword" style="color: #333333; font-weight: bold;">var</span> someData = [<span class="number" style="color: #009999;">1</span>,<span class="number" style="color: #009999;">4</span>,<span class="number" style="color: #009999;">2</span>,<span class="number" style="color: #009999;">4</span>,<span class="number" style="color: #009999;">5</span>,<span class="number" style="color: #009999;">6</span>];
<span class="keyword" style="color: #333333; font-weight: bold;">var</span> results = _.chain(someData)
.sortBy(_.identity)
.filter(<span class="keyword" style="color: #333333; font-weight: bold;">function</span>(a){<span class="keyword" style="color: #333333; font-weight: bold;">return</span> a><span class="number" style="color: #009999;">3</span>})
.map(<span class="keyword" style="color: #333333; font-weight: bold;">function</span>(m){<span class="keyword" style="color: #333333; font-weight: bold;">return</span> m*m})
.value(); <span class="comment" style="color: #999988; font-style: italic;">// that's the piece which 'executes' the chain</span>
<span class="comment" style="color: #999988; font-style: italic;">//outputs [16, 16, 25, 36]</span></code></pre>
<div style="margin: 1.2em 0px !important;">
You judge which one is better!</div>
</div>
</div>
Alexanderhttp://www.blogger.com/profile/10093762646999402082noreply@blogger.com0tag:blogger.com,1999:blog-5866514577340267046.post-28623851296050913992013-10-08T10:59:00.002+03:002013-10-08T10:59:27.932+03:00Domain name history search tool - found a non-paid one!<div dir="ltr" style="text-align: left;" trbidi="on">
<div class="markdown-here-wrapper" data-md-original="%3Cp%3EHi%20there%2C%26nbsp%3B%3C%2Fp%3E%3Cp%3E%3Cbr%3E%3C%2Fp%3E%3Cp%3EI%20was%20fighting%20the%20DNS%20system%20recently%2C%20and%20GoDaddy%20to%20name.%20Issue%20was%20that%20I%20was%20changing%20the%20nameservers%20for%20a%20given%20domain%20name%2C%20but%20for%20some%20reason%20GoDaddy%20disallowed%20to%20forward%20that%20domain.%20This%20worked%20out%20pretty%20well%20afterwards%20(just%20takes%20some%20time%20to%20wait).%3C%2Fp%3E%3Cp%3E%3Cbr%3E%3C%2Fp%3E%3Cp%3EHowever%20I%20made%20a%20*mistake*%20then.%20I%20have%20changed%20the%20NS%20servers%2C%20without%20writing%20down%20the%20old%20ones.%20When%20the%20change%20was%20done%2C%20I%20was%20unable%20to%20recover%20original%20IP%20of%20the%20service%20I%20was%20moving%20(oh%20sh!).%3C%2Fp%3E%3Cp%3E%3Cbr%3E%3C%2Fp%3E%3Cp%3EThat%20was%20a%20moment%20of%20panic%2C%20however%2C%20after%20some%20searching%20I%20have%20come%20across%20(a%20finally%20free!)%20tool%2C%20which%20shows%20the%20history%20of%20the%20domain%20name%20change%20over%20time.%26nbsp%3B%3C%2Fp%3E%3Cp%3E%3Cbr%3E%3C%2Fp%3E%3Cp%3EThat's%26nbsp%3B%3Ca%20href%3D%22http%3A%2F%2Fwhoisrequest.org%2Fhistory%2F%22%3Ehttp%3A%2F%2Fwhoisrequest.org%2Fhistory%2F%3C%2Fa%3E%2C%20and%20it%20works%20just%20perfectly.%20Using%20it%2C%20I%20was%20able%20to%20find%20out%20the%20historical%20NS%20records%2C%20and%20then%20query%20it%20for%20the%20old%20IP%20and%20it%20was%20relief%20%3A)%26nbsp%3B%3C%2Fp%3E" data-md-url="http://www.blogger.com/blogger.g?blogID=5866514577340267046#editor/target=post;postID=2862385129605091399" id="markdown-here-wrapper-981229">
<div style="margin: 1.2em 0px !important;">
Hi there, </div>
<div style="margin: 1.2em 0px !important;">
I was fighting the DNS system recently, and GoDaddy to name. Issue was that I was changing the nameservers for a given domain name, but for some reason GoDaddy disallowed to forward that domain. This worked out pretty well afterwards (just takes some time to wait).</div>
<div style="margin: 1.2em 0px !important;">
However I made a <em>mistake</em> then. I have changed the NS servers, without writing down the old ones. When the change was done, I was unable to recover original IP of the service I was moving (oh sh!).</div>
<div style="margin: 1.2em 0px !important;">
That was a moment of panic, however, after some searching I have come across (a finally free!) tool, which shows the history of the domain name change over time. </div>
<div style="margin: 1.2em 0px !important;">
That’s <a href="http://whoisrequest.org/history/"></a><a href="http://whoisrequest.org/history/">http://whoisrequest.org/history/</a>, and it works just perfectly. Using it, I was able to find out the historical NS records, and then query it for the old IP and it was relief :) </div>
</div>
</div>
Alexanderhttp://www.blogger.com/profile/10093762646999402082noreply@blogger.com0tag:blogger.com,1999:blog-5866514577340267046.post-72402005679667104352013-10-04T13:26:00.002+03:002013-10-04T13:26:42.370+03:00Setting up TeamCity coverage report for node.js test with mocha and jscoverage<div dir="ltr" style="text-align: left;" trbidi="on">
Hi!<br />
<br />
The mentioned tech stack has been popular for quite a while, leading to many people using it (especially in startups, for quick and robust API implementations, etc.). The question of testing is solved quite well (there is a number of testing, mocking, assert frameworks out there which I find astonishing).<br />
<br />
This post is about quite a regular task on how to setup coverage metrics automatically on the build server (TeamCity is my favourite).<br />
<br />
Disclaimer: I have a strong belief that coverage metrics should never be given to the business people w/out tech control. When they see _any_ metrics, they become excited with it and we have that overused. I believe, that coverage should be used by developers themselves to see what code paths have not been tested, and what tests can they add.<br />
<br />
<br />
So, let's start. Prerequisites:<br />
<br />
<ol style="text-align: left;">
<li>You have mocha tests</li>
<li>You have a working installation of TeamCity, which is already pulling the sources from repo, building app, running these tests on post-commit basis (and surely sends notifications to the people in charge).</li>
<li>You want to add coverage metrics to the party to see what's the progress and what areas need more help. </li>
</ol>
<div>
Given that your project structure knows nothing of jscoverage, we'll go least-intrusive, scripting way. </div>
<div>
<br /></div>
<h3 style="text-align: left;">
Jscoverage</h3>
<div>
<a href="https://npmjs.org/package/jscoverage">https://npmjs.org/package/jscoverage</a></div>
<div>
You need a specific jsCoverage build, which knows about node. You can have that installed, as usual, with npm:</div>
<div>
</div>
<div>
<span style="font-family: Courier New, Courier, monospace;">npm install -g jscoverage</span></div>
<div>
<span style="font-family: Courier New, Courier, monospace;"><br /></span></div>
<div>
Verify the install, by issuing jscoverage on the commandline. The output is not very helpful, but gives the most interesting parameters you'll need. </div>
<div>
<br /></div>
<div>
The way all coverage tools work is that either instrument the product of your code (or code itself, for scripting tools), OR plug into the interpreter, and when you apply some interaction to this code (tests, users coming in and out, etc), collect how many times each of the lines was called. After these numbers are obtained, static analysis may plug in to verify how many functions/branches/conditions were covered. </div>
<div>
<br /></div>
<div>
So, we need to obtain such an 'instrumented' code first from our target code. That's what jscoverage doing:</div>
<div>
<br /></div>
<br />
<div>
<span style="font-family: Courier New, Courier, monospace;">jscoverage --exclude tests,node_modules,.git,target,.idea CURRENT_FOLDER OUTPUT_FOLDER</span></div>
<div>
<span style="font-family: Courier New, Courier, monospace;"><br /></span></div>
<div>
<span style="font-family: Arial, Helvetica, sans-serif;">After that you can examine the results in the output folder. All your files should be copied there (except the ones included), and they should have some weird code inside (that's the recording part!), with pieces and bits of your code scattered across the file. </span></div>
<div>
<span style="font-family: Arial, Helvetica, sans-serif;"><br /></span></div>
<h3 style="text-align: left;">
<span style="font-family: Arial, Helvetica, sans-serif;">mocha</span></h3>
<div>
<span style="font-family: Arial, Helvetica, sans-serif;">As you are already probably using mocha for testing, nothing is really tough here. I assume that you are loading your modules-under-test with the require('../../lib/something'), rather than via absolute paths. </span></div>
<div>
<span style="font-family: Arial, Helvetica, sans-serif;"><br /></span></div>
<div>
<span style="font-family: Arial, Helvetica, sans-serif;">As we already have a specific folder, which contains jscoverage-processed main app code, w/out all the unnecessary folders, we could now just copy out the tests themselves to that folder, and run mocha. No results yet, we just verify that mocha tests run with our processed code. </span></div>
<div>
<span style="font-family: Arial, Helvetica, sans-serif;"><br /></span></div>
<div>
<span style="font-family: Arial, Helvetica, sans-serif;">Next, we are good to go to add some html-cov reporting. This reporter is already bundled with mocha, so no need to reference it in package.json. what it does, is that after the mocha tests are ran, it gets the coverage statistics from coverage-augmented files under test, and flushes that (in form of HTML) to the stdout. So, to see what's in the coverage, we do (whilst in the OUTPUT_FOLDER): </span></div>
<div>
<span style="font-family: Arial, Helvetica, sans-serif;"><br /></span></div>
<div>
<span style="font-family: Courier New, Courier, monospace;">../.././node_modules/mocha/bin/mocha -t 20000 --noinject --reporter html-cov --recursive ./tests/ --coverage</span></div>
<div>
<br /></div>
--noinject is required for me, as I am using rewire library for testing, and that somehow clashes with the jscoverage stuff.<br />
<br />
You could divert that output to file, or just pipe to w3m.<br />
<br />
<h3 style="text-align: left;">
TeamCity</h3>
<div>
Quite an easy part now; since we have all working locally on the server, we just need to automate it. I have finally used a html-file-cov mocha reporter, it prints out the tests results as dots to the stdout, and writes the coverage report to coverage.html within working folder; quite an easy and handy tool. <a href="https://npmjs.org/package/html-file-cov">https://npmjs.org/package/html-file-cov</a></div>
<div>
<br /></div>
<div>
In teamcity, we need to add another build step to the post-commit configuration. I did the easy and ugly script way instead of built-in report processing, since I was quite happy with the html format. </div>
<div>
<br /></div>
<div>
So, as we have added that build step (of type Custom script), we could now fill it with the actual logic: </div>
<div>
<br /></div>
<div>
<div>
<span style="font-family: Courier New, Courier, monospace;">#!/bin/bash</span></div>
<div>
<span style="font-family: Courier New, Courier, monospace;"><br /></span></div>
<div>
<span style="font-family: Courier New, Courier, monospace;">rm -rf ../target-cov/*</span></div>
<div>
<span style="font-family: Courier New, Courier, monospace;">rm -rf ./target/target-cov</span></div>
<div>
<span style="font-family: Courier New, Courier, monospace;">rm -rf ./target/coverage.html</span></div>
<div>
<span style="font-family: Courier New, Courier, monospace;"><br /></span></div>
<div>
<span style="font-family: Courier New, Courier, monospace;">mkdir -p ../target-cov</span></div>
<div>
<span style="font-family: Courier New, Courier, monospace;">jscoverage --exclude tests,node_modules,.git,target,.idea . ../target-cov</span></div>
<div>
<span style="font-family: Courier New, Courier, monospace;"><br /></span></div>
<div>
<span style="font-family: Courier New, Courier, monospace;">mv ../target-cov ./target</span></div>
<div>
<span style="font-family: Courier New, Courier, monospace;">cp -r ./tests ./target/target-cov</span></div>
<div>
<span style="font-family: Courier New, Courier, monospace;">echo "JS files instrumented correctly"</span></div>
<div>
<span style="font-family: Courier New, Courier, monospace;"><br /></span></div>
<div>
<span style="font-family: Courier New, Courier, monospace;">cd target/target-cov</span></div>
<div>
<span style="font-family: Courier New, Courier, monospace;">echo "Running mocha tests with 'dot' reporter"</span></div>
<div>
<span style="font-family: Courier New, Courier, monospace;">NODE_ENV=dev ../.././node_modules/mocha/bin/mocha -t 20000 --noinject --reporter html-file-cov --recursive ./tests/ --coverage</span></div>
<div>
<span style="font-family: Courier New, Courier, monospace;">mv ./coverage.html ..</span></div>
<div>
<span style="font-family: Courier New, Courier, monospace;">echo "Done. Configuration stored to `pwd`/../coverage.html"</span></div>
</div>
<div>
<br /></div>
<div>
<br /></div>
<div>
As a result of this manipulation (making a dir one level up, storing there the jscoverage-processed files, copying it to the local 'target' folder, copying over the tests non-processed, running the tests, moving the coverage.html to the target dir), we have the artifact - coverage.html - which contains all the stuff we need. </div>
<div>
<br /></div>
<div>
We just need to publish it - in TeamCity project settings, on the very first page, there's an 'Artifacts' box, which takes paths. Just add +:target/coverage.html, and after each build you'll have a nice drop-down 'Artifacts' with a link to your html with coverage. </div>
<div>
<br /></div>
<div>
Voila! </div>
<div>
</div>
<div>
</div>
</div>
Alexanderhttp://www.blogger.com/profile/10093762646999402082noreply@blogger.com0tag:blogger.com,1999:blog-5866514577340267046.post-60446692222105597742013-03-13T14:36:00.001+02:002013-03-13T14:36:19.785+02:00Portecle - nice tool to manage certificates, keystores, keys, etc. Instead of keytool (jdk)<div dir="ltr" style="text-align: left;" trbidi="on">
I was using keytool from jdk installation always. However, when it came down to bouncycastle implementation, too much work should be done to make it running - download a crypto provider, install it, etc. That's the description: <a href="http://stackoverflow.com/questions/4065379/how-to-create-a-bks-bouncycastle-format-java-keystore-that-contains-a-client-c">http://stackoverflow.com/questions/4065379/how-to-create-a-bks-bouncycastle-format-java-keystore-that-contains-a-client-c</a><br />
<br />
As Android uses bouncycastle by default, had to pack a public key of the RSA pair to the BKS store to make a resilient HttpsUrlConnection.<br />
<br />
Found it very nice and handy to use <a href="http://portecle.sourceforge.net/">http://portecle.sourceforge.net/</a> as a GUI tool.<br />
<br />
Works flawlessly, recommended</div>
Alexanderhttp://www.blogger.com/profile/10093762646999402082noreply@blogger.com0tag:blogger.com,1999:blog-5866514577340267046.post-37414475971506491272013-03-12T08:33:00.000+02:002013-03-12T08:37:07.234+02:00Linux/mac alternative to Fiddler - WebScarab!<div dir="ltr" style="text-align: left;" trbidi="on">
I really enjoy using <a href="http://www.fiddler2.com/fiddler2/">fiddler</a> - that is web logging proxy, or, the way it is called - a web debugger.<br />
<br />
It works very easy way:<br />
<br />
<ol style="text-align: left;">
<li>When started, modifies the Internet Explorer proxy settings to point them on itself.</li>
<li>All the request are logged and ready to be analyzed then. </li>
<li>As much of the software does use IE proxy settings for its own setup, non-straightforward things as SOAP calls, Ajax, embedded-browser calls may also be caught. </li>
<li>With the captured interchange, one can analyze every aspect of a single roundtrip.</li>
</ol>
<div>
The only thing I dislike about it is its nature - .Net built, it works flawlessly on MS platform, but not on Linux.</div>
<div>
<br /></div>
<div>
The good and working alternative I have found is <a href="https://www.owasp.org/index.php/Category:OWASP_WebScarab_Project">webscarab</a> project, which is written in java, looks pretty much the same, and does most of the same job. Easy thing. Just run it with java-jar and setup your software to proxy through 127.0.0.1:8008.</div>
<div>
<br /></div>
</div>
Alexanderhttp://www.blogger.com/profile/10093762646999402082noreply@blogger.com0tag:blogger.com,1999:blog-5866514577340267046.post-4264008259790003302013-03-11T17:52:00.000+02:002013-03-11T17:52:20.749+02:00Web-harvest scrapper 2.1 - how to use<div dir="ltr" style="text-align: left;" trbidi="on">
Often it happens that you need to get some data from a web source, but the developers of the site disallow or simply do not have resources to implement any b2b API.<br />
<br />
That's where scrapers come in. They are software pieces acting as a browser but providing some programmatic API to process results in a program code.<br />
<br />
During my search for an acceptable solution, I came over the <a href="http://web-harvest.sourceforge.net/">http://web-harvest.sourceforge.net/</a> ; nice features are:<br />
<br />
<ol style="text-align: left;">
<li>All-java, used as a library</li>
<li>Great versatility - it is packed; really. Xquery, Xpath, regex searches, emulation of browser activity, templating and variables, different script integration. </li>
<li>Nice UI workbench, which allows to develop scripts easily and see the results immediately. Then, just save the XML configuration and invoke it from the code then. </li>
</ol>
<div>
However, the version under link above is 2.0 version. It is not present in Maven, and I am building with maven. However, there is a new 2.1 version, which is highly redone - maven build process, switched to <a href="https://code.google.com/p/google-guice/">Guice</a> injection, etc. </div>
<div>
<br /></div>
<div>
I fancy 2.1 alot, but there are some issues with it - NO documentation at all, a little different behavior. I made a fork for myself on GitHub (<a href="https://github.com/lexaux/web-harvest">https://github.com/lexaux/web-harvest</a>) - and applying changes there. Hopefully, will be able to contact developers and contribute. </div>
<div>
<br /></div>
<div>
For now, a quick how-to on running the 2.1 web-harvest scraper in your code (UI is pretty straightforward). It is really different from 2.0. So, here it goes:</div>
<div>
<br />
<script class="brush: java" type="syntaxhighlighter"><![CDATA[
Injector scraperGuiceInjector = Guice.createInjector(
new ScraperModule("."),
new HttpModule(settings));
Harvest harvest = scraperGuiceInjector.getInstance(Harvest.class);
ConfigSourceFactory configSourceFactory =
scraperGuiceInjector.getInstance(ConfigSourceFactory.class);
String config = IOUtils.toString(getClass().getResourceAsStream("/wizzair-scraper.xml"));
ConfigSource configSource = configSourceFactory.create(config);
Harvester harvester = harvest.getHarvester(EntryPoint.configSource, new HarvestLoadCallback()
{
@Override
public void onSuccess(List<IElementDef> elements)
{
LOGGER.info("Successfully initialized web scrapper - the configuration is loaded now.");
}
});
DynamicScopeContext context = harvester.execute(new Harvester.ContextInitCallback()
{
@Override
public void onSuccess(DynamicScopeContext context)
{
// Do not be confused with this - this is INIT success callback, not the execution.
LOGGER.info("Harvester initialization successful.");
}
});
// Obtain the variables from the execution. These are coming from a web page loaded and processed.
String price = context.getVar("price").toString();
]]></script>
</div>
</div>Alexanderhttp://www.blogger.com/profile/10093762646999402082noreply@blogger.com4tag:blogger.com,1999:blog-5866514577340267046.post-17456339357633472302013-02-28T13:17:00.000+02:002013-10-02T07:27:47.090+03:00Building Android application with Maven -- Unknown packaging APK<div dir="ltr" style="text-align: left;" trbidi="on">
Should have been an easy thing. However, I spent my own 15 minutes because of not following rules. So here they are for starting up with maven and android: <br />
<br />
<ol style="text-align: left;">
<li>Read the Getting Started here <a href="http://code.google.com/p/maven-android-plugin/wiki/GettingStarted">http://code.google.com/p/maven-android-plugin/wiki/GettingStarted</a></li>
<li>Create your own pom.xml, copying one from one of the samples. Samples can be downloaded also from Google code: <a href="http://code.google.com/p/maven-android-plugin/wiki/Samples">http://code.google.com/p/maven-android-plugin/wiki/Samples</a></li>
</ol>
<div>
After performing these steps, I was unable to proceed, unfortunately. I had an error from maven build saying that my pom is not correct - looks like it did not pick up the android plugin, and thus did not understand the apk packaging. </div>
<div>
<br /></div>
<div>
<span style="font-family: Courier New, Courier, monospace;">Unknown packaging: apk @ line 15, column 16</span></div>
<div>
<span style="font-family: Courier New, Courier, monospace;"><br /></span></div>
<div>
<span style="font-family: Arial, Helvetica, sans-serif;">So i started lurking around and got the difference soon. I missed a single line in declaring a build plugin. Without the <extensions> element, maven is not picking the new packaging. Oh, and also - the plugin requires maven 3.0.3 or newer. </extensions></span></div>
<div>
<span style="font-family: Arial, Helvetica, sans-serif;"><br /></span></div>
<div>
<span style="font-family: Arial, Helvetica, sans-serif;">This is my entire Build section:</span><br />
<span style="font-family: Arial, Helvetica, sans-serif;"><br /></span></div>
<span style="font-family: Arial, Helvetica, sans-serif;">Build/plugins section:</span><br />
<script class="brush: xml" type="syntaxhighlighter"><![CDATA[
<plugin>
<groupid>com.jayway.maven.plugins.android.generation2</groupId>
<artifactid>android-maven-plugin</artifactId>
<extensions>true</extensions>
<configuration>
<sign>
<debug>false</debug>
</sign>
</configuration>
</plugin>
]]></script>
<span style="font-family: Arial, Helvetica, sans-serif;">Dependencies section:</span><br />
<script class="brush: xml" type="syntaxhighlighter"><![CDATA[
<dependency>
<groupid>com.google.android</groupId>
<artifactid>android</artifactId>
<version>4.0.1.2</version>
<scope>provided</scope>
</dependency>
]]></script>
</div>Alexanderhttp://www.blogger.com/profile/10093762646999402082noreply@blogger.com2tag:blogger.com,1999:blog-5866514577340267046.post-90031886361925166132013-02-23T23:21:00.001+02:002013-02-23T23:21:47.599+02:00How to build gwt 2.4 now -- if errors in build<div dir="ltr" style="text-align: left;" trbidi="on">
Okay, so the goal is to build Google Web Toolkit of version 2.4 now - when 2.5 is a current stable. Issues seems to be fairly easy, but unfortunately -- fails from the first approach. Continuing tradition of writing memos for future, here it goes:<br />
<br />
<ol style="text-align: left;">
<li><a href="http://google-web-toolkit.googlecode.com/svn/releases/2.4/">http://google-web-toolkit.googlecode.com/svn/releases/2.4/</a> - Main GWT source, release 2.4, checkout with subersion.</li>
<li><a href="http://google-web-toolkit.googlecode.com/svn/tools/">http://google-web-toolkit.googlecode.com/svn/tools/</a> - GWT-tools, some binary dependencies required for building.<br />Trick is that they are versioned in a streamlined manner, and no-one leaves a note about which version of the tools does particular version of GWT require to build.<br />So - to note, for GWT release 2.4 Tools rev 10417 are required. Do update Tools repo to this revision. </li>
<li>Next step is straightforward - just set GWT_TOOLS environment variable to point to the tools working copy contianing rev 10417, descend into the GWT 2.4 release working copy, and issue ant.<br /><br />It did not work for me<br /><span style="font-family: Courier New, Courier, monospace;"><span style="background-color: white; color: #222222; font-size: 13px;">[gwt.javac] /home/lexaux/work/gwt/2_4/</span><wbr style="color: #222222; font-size: 13px;"></wbr><span style="background-color: white; color: #222222; font-size: 13px;">user/src/com/google/web/</span><wbr style="color: #222222; font-size: 13px;"></wbr><span style="background-color: white; color: #222222; font-size: 13px;">bindery/requestfactory/shared/</span><wbr style="color: #222222; font-size: 13px;"></wbr><span style="background-color: white; color: #222222; font-size: 13px;">impl/FindRequest.java:34: error: <b>name clash: find(EntityProxyId) in FindRequest and find(EntityProxyId) in RequestContext have the same erasure, yet neither overrides the other</b></span></span><div style="background-color: white; border: 0px; color: #222222; font-size: 13px; margin: 0px; padding: 0px; vertical-align: baseline;">
<span style="font-family: Courier New, Courier, monospace;">[gwt.javac] Request<entityproxy> find(EntityProxyId proxy);</entityproxy></span></div>
<br />Which is fairly weird, I thought, as ant explicitly sets language and class output level.<br />After about a day of search, I just tried to downgrade my JDK to version 6 -- and voila; it worked. Looks like there is a change in generic treatment which stopped compilation.<br /></li>
</ol>
<div>
After successful build, you can obtain results in build/lib - here's gwt-dev.jar and gwt-user.jar</div>
</div>
Alexanderhttp://www.blogger.com/profile/10093762646999402082noreply@blogger.com0tag:blogger.com,1999:blog-5866514577340267046.post-37643315269894649282013-01-30T09:13:00.004+02:002013-01-30T09:13:29.710+02:00Java to Scala idioms: id list from object list<div dir="ltr" style="text-align: left;" trbidi="on">
Well, i was amazed.<br />
<br />
I just needed to get a list of IDs of database-stored objects, in order to pass them for later-on updates with the 'where ... in' query. And got that with scala mind-blowing way. Instead of Java (please omit comments about lots of auto-boxing and array creation etc -- its only verbosity-related sample):<br />
<br />
<span style="font-family: Courier New, Courier, monospace;">List<dbobject> dbObjects = ...</dbobject></span><br />
<span style="font-family: Courier New, Courier, monospace;">ArrayList<integer> idArray = new ArrayList<integer>(dbObjects.size());</integer></integer></span><br />
<span style="font-family: Courier New, Courier, monospace;">for(DBObject o : dbObjects) {</span><br />
<span style="font-family: Courier New, Courier, monospace;"> idArray.add(o.getId());</span><br />
<span style="font-family: Courier New, Courier, monospace;">}</span><br />
<br />
I would just write something like<br />
<br />
<span style="font-family: Courier New, Courier, monospace;">val ids = dbObjects.map(_.getId)</span><br />
<br />
And that's it!<br />
<br />
Moreover, I'm now using <a href="http://slick.typesafe.com/">slick</a> with lifted embedding. For it, i need to map objects I want to store in DB to tuples consistent with db schema (prior to insert). I'm now about to do this by providing a mapping function in the Table descendants describing DB schema, and using it whenever I want to store objects. Just need to think of types a bit so it is consistent,but general use would be, instead of:<br />
<br />
<span style="font-family: Courier New, Courier, monospace;">DBObjects.insertAll(objects.map(x => (x.id, x.name, ...)) </span><br />
<br />
I would use<br />
<br />
<span style="font-family: Courier New, Courier, monospace;">DBObjects.insertAll(objects)</span>, while inside this thing would use its own mapping functions.<br />
Great stuff about it is that it is all compile-time checked -- e.g, if I change schema, I will get compilation errors about the tuples don't match on that conversion function.<br />
<br />
Isn't that nice?</div>
Alexanderhttp://www.blogger.com/profile/10093762646999402082noreply@blogger.com0tag:blogger.com,1999:blog-5866514577340267046.post-1052526190904245602013-01-28T13:27:00.000+02:002013-01-28T13:27:30.075+02:00sbt and IntelliJ idea support<div dir="ltr" style="text-align: left;" trbidi="on">
For now, not so as good as Maven integration, however worth seeing.<br />
Found:<br />
<br />
<ol style="text-align: left;">
<li><a href="https://github.com/mpeltonen/sbt-idea">https://github.com/mpeltonen/sbt-idea</a> - SBT plugin for generating IDEA files (.idea structure, not the old one) from the SBT build definition.<br />Unfortunately, the project created is not ideal -- it adds some additional module for SBT build itself, and in my case it picked up wrong web.xml for webapp.<br />It is OK to change this, <i>however as soon as you add another one lib in SBT, you'll have to re-generate and re-configure IDEA again. </i></li>
<li><a href="https://github.com/orfjackal/idea-sbt-plugin/wiki">https://github.com/orfjackal/idea-sbt-plugin/wiki</a> - IDEA plugin to run SBT commands in IDE, include to the build process and show notifications in-place. Not too bad. </li>
</ol>
<div>
Issues with those are that, not alike maven integration, IDEA does not track automatically changes in SBT, and on re-configuration of the build some work is needed. </div>
<div>
<br /></div>
<div>
On the side, just an idea whether it is possible at all. Maven's pom.xml provides ready model, while SBT provides a set of transformations - some of them may be pretty complex. One would need to run sbt behind IDEA to gather the actual ending values of the Setting[T] at the end. I guess :)</div>
</div>
Alexanderhttp://www.blogger.com/profile/10093762646999402082noreply@blogger.com0tag:blogger.com,1999:blog-5866514577340267046.post-80144371739398996762013-01-22T20:41:00.000+02:002013-01-22T20:41:05.941+02:00Android HttpsUrlConnection, self-signed certificate and hostname verifier<div dir="ltr" style="text-align: left;" trbidi="on">
Today, an Android hint. Note for myself for future :)<br />
<br />
So, what we have:<br />
<br />
<ol style="text-align: left;">
<li>Server<br />REST (JAX-RS+akka), published to Tomcat. Tomcat serves app via HTTPS having a self-signed certificate (<a href="http://tomcat.apache.org/tomcat-6.0-doc/ssl-howto.html">official tomcat docs</a>).<br />No CA, no chain - just a single certificate done in a really usual way.<br />Tomcat is published on a box accessible only via IP, no DNS here.<br />The actual server is <a href="https://46.4.224.49/">https://46.4.224.49</a> just in case someone wants to take a look @cert.</li>
<li>Client<br />Android, trying to talk to the server above in JSON. Should use HTTPS for both traffic encryption and identity confirmation.</li>
</ol>
<div>
Generally, implementation seems pretty straightforward - get the public certificate, and make Android https facilities to trust it. </div>
<div>
<br /></div>
<div>
I decided to use HttpsUrlConnection rather than HttpClient as the documentation suggest the former was only preferred for small operations in Android versions prior to 3. Trick is that Android is not shipped with the JKS keystore implementation which seems to belong to Oracle (Sun before).</div>
<div>
<br /></div>
<div>
After some googling I combined 3 articles to make a good working example:</div>
<div>
<ol style="text-align: left;">
<li><a href="http://blog.crazybob.org/2010/02/android-trusting-ssl-certificates.html">http://blog.crazybob.org/2010/02/android-trusting-ssl-certificates.html</a><br />use first 2 steps, how to obtain public certificate off the server, pack it to the BKS keystore and some clues on how to setup BouncyCastle<br />(hint - as of early 2013 we need version bcprov-jdk15on-146.jar, though newer is there)<br />Added correct line to jre/lib/security/java.security to support another one provider, and dropped the jar into jre/lib/ext. This is only needed for keytool to understand new format.</li>
<li><a href="http://developer.android.com/reference/javax/net/ssl/HttpsURLConnection.html">http://developer.android.com/reference/javax/net/ssl/HttpsURLConnection.html</a><br />Feed HttpsUrlConnection with the SslSocketFactory relying on that keystore. Keystore is put into the res/raw and loaded via <span style="font-family: Courier New, Courier, monospace;">context.getResources().openRawResource(int id)</span></li>
</ol>
<div>
<span style="font-family: Arial, Helvetica, sans-serif;">And this is where the trouble started. The test code was producing error. After getting the certificate in the error has changed from 'Not trusted certificate' to 'Can not verify hostname'. Which is progress. </span></div>
</div>
<div>
<br /></div>
<div>
The very major of the solutions on the Internet were just allowing all the hostname, and even deeper, accepting all the certificates -- which was inacceptable due to security reason.</div>
<div>
<br /></div>
<div>
<span style="font-family: Arial, Helvetica, sans-serif;">The certificate had an IP address in CN field. After some research, it was clear that certificate is there, it is trusted, however hostname check fails. That's when <a href="http://www.androidjavadoc.com/1.0_r1_src/javax/net/ssl/DefaultHostnameVerifier.html">DefaultHostnameVerifier</a> was spotted (yes i know javadoc is old, but debugger shows this very class, which is hidden in library-no source). However, old javadoc says clearly that all the checks are declined!</span></div>
<div>
<span style="font-family: Arial, Helvetica, sans-serif;"><br /></span></div>
<div>
<span style="font-family: Arial, Helvetica, sans-serif;">Surely we can not have this check passed as <i>nothing</i> is allowed. </span></div>
<div>
<span style="font-family: Arial, Helvetica, sans-serif;"><br /></span></div>
<div>
<span style="font-family: Arial, Helvetica, sans-serif;">The issue is resolved easily with setting </span><span style="font-family: Courier New, Courier, monospace;">conn.setHostnameVerifier(new BrowserCompatHostnameVerifier())</span> - this triggers <span style="font-family: Courier New, Courier, monospace;">HttpsUrlConnection</span> to the same mode as the browser (passing *.domain CNs, and IP addresses, etc), which is perfectly OK for our case. </div>
<div>
</div>
</div>
Alexanderhttp://www.blogger.com/profile/10093762646999402082noreply@blogger.com4tag:blogger.com,1999:blog-5866514577340267046.post-48533683366646569982012-04-12T19:50:00.001+03:002012-04-12T19:51:29.951+03:00Site of the company I Work ForHappy to announce that we have finally gone public - <a href="http://www.logicify.com">http://www.logicify.com</a><div><br /><div>Software service to your service :) </div></div>Alexanderhttp://www.blogger.com/profile/10093762646999402082noreply@blogger.com2tag:blogger.com,1999:blog-5866514577340267046.post-26771531053880515752011-12-22T15:18:00.005+02:002011-12-22T21:40:29.424+02:00MySQL failover talkHi! Today I had a talk at local IT user group regarding the MySQL fault-tolerance cluster. No original research neither anything specific - just a bit of experience which may help you setup the same easier ;).<div><br /></div><div>The slides are in Russian: <a href="https://docs.google.com/present/view?id=df6sccnc_72gkk5dmck">https://docs.google.com/present/view?id=df6sccnc_72gkk5dmck</a></div><div><br /></div><div>Alternatively you can look at them locally here:</div><div><br /></div><br /><iframe src="https://docs.google.com/present/embed?id=df6sccnc_72gkk5dmck" frameborder="0" width="410" height="342"></iframe>Alexanderhttp://www.blogger.com/profile/10093762646999402082noreply@blogger.com0tag:blogger.com,1999:blog-5866514577340267046.post-44608456961268584892011-12-22T07:37:00.003+02:002011-12-22T08:00:22.127+02:00Wicket 1.4 modal window not hiding contents in hierarchy on close! :oLooks like plenty of the posts are for myself not to forget about 'specific' issues found in the frameworks during the development. Well, wicket 1.4.(18?) this time.<div><br /></div><div><b>The problem</b></div><div>So, we have a modal window. There is a form (call it form2) in this modal window. For the last, modal window itself is within a form (call it form1). Hierarchy looks like form1 <- modal window <- form2.</div><div><br /></div><div>Both form1 and form2 have validators for their components, and both do have submitting components. </div><div><br /></div><div>When the MW is shown and visible, everything works just fine according to the <a href="http://www.google.com.ua/search?gcx=c&sourceid=chrome&client=ubuntu&channel=cs&ie=UTF-8&q=wicket+nested+forms">Nested form </a>rules of the wicket. However, as you close the modal window by any means, the form2 will still be validated on the submit of form1! However, as it is _not_ visible on client (modal window is closed) we can not show to user what's wrong, they actually don't have access to the components failing. </div><div><br /></div><div><div>Wicket modal windows do close by means of Ajax. E.g. when the actual DOM element is hidden by clicking cross, or outside modal window, or close button, wicket issues an ajax-call to server to notify it that window is no more visible. </div><div><br /></div><div>This call is handled by <i>WindowClose </i>behavior, the subclass of <i>AbstractAjaxDefaultBehavior.</i>For greater detail you may take a look at it in the <i>ModalWindow</i> class. What this behavior does in the original implementation: </div><div><ol><li>Reset shown flag to <i>false</i>, so window will be opened again when next time <i>show(target)</i> is invoked.</li><li>In case of the modal window showing pages, not components, do cleanup of the pagemap.</li><li>Invoke <i>WindowCloseListener</i> instance (if any has been set to this ModalWindow).</li></ol><div>That's it. It means that <b>closing modal window</b> <b>does not hide the components inside it </b>from the wicket hierarchy, and they are treated as visible however they are not really! </div></div></div><div><br /></div><div><b>The solution</b></div><div>General solution for me was to hide content on the modal window close action. </div><div>2 approaches:</div><div><ol><li>Local.<br />Just implement the windowClosedCallback, pass it to the instance of modal window, and in it, do hide your content on the close action.<br />Bad things are that if you are developing a reusable component, you may want clients of this component to use windowClosedCallback for their own stuff.<br /><br /></li><li>General.<br />Subclass a ModalWindow. Say, <i>MyModalWindow extends ModalWindow<br /><br /></i></li><li>Override<i> newWindowClosedBehavior()</i> of it<br /><br /></li><li>In this method, create your own ajax behavior doing same thing as wicket does, plus hide component if it is there. Pass it on to the return. Voila, we are done. </li></ol><div>Now the components will be really hidden, and you won't be getting nested forms edgecase validation issues (or whatever else hiding there - I don't really know). </div></div><div><br /></div><div>That's the code snippet:</div><div><div><br /></div><div>//... inside our ModalWindow subclass, MyModalWindow</div><div> <i> private class MyModalWindowClosedBehavior extends AbstractDefaultAjaxBehavior</i></div><div><i> implements</i></div><div><i> IWindowClosedBehavior {</i></div><div><i> private static final long serialVersionUID = 1L;</i></div><div><i><br /></i></div><div><i> @Override</i></div><div><i> protected void respond(AjaxRequestTarget target) {</i></div><div><i> respondOnWindowClosed(target); // that'd be a call to the wicket's MW behavior.</i></div><div><i> if (getContent() != null) {</i></div><div><i> getContent().setVisible(false);</i></div><div><i> }</i></div><div><i> }</i></div><div><i><br /></i></div><div><i> @Override</i></div><div><i> public CharSequence getCallbackScript() {</i></div><div><i> return super.getCallbackScript();</i></div><div><i> }</i></div><div><i> }</i></div><div><i><br /></i></div><div><i> @Override</i></div><div><i> protected IWindowClosedBehavior newWindowClosedBehavior() {</i></div><div><i> return new PoseidonWindowClosedBehavior();</i></div><div><i> }</i></div></div><div><br /></div>Alexanderhttp://www.blogger.com/profile/10093762646999402082noreply@blogger.com0tag:blogger.com,1999:blog-5866514577340267046.post-17179464350613397242011-12-20T08:33:00.003+02:002011-12-20T08:49:20.647+02:00Inform user about Ajax failed (no network) in Wicket<b>The problem</b><div><b><br /></b></div><div>It is well known to the internet. If you have an Ajax application you have to somehow inform user in case Ajax fails. And in the modern world Ajax may fail very easily - WiFi switched off, bad smartphone connection et al. </div><div><br /></div><div>Also we have a Wicket which does hide all the Ajax work behind the scenes - you drop components to the page, they do communicate via Ajax.</div><div><br /></div><div><b>The (possible) solution</b></div><div>At least we employed the one for us.</div><div><br /></div><div><b>1.</b> Create the localized message key in the property file. We are using XML properties, so it'd look like <i><entry key="ajaxCommunicationFailedMessage">Ajax failed! Reload please</entry></i></div><div><i><entry key="ajaxCommunicationFailedMessage"><br /></entry></i></div><div><b>2.</b><i> </i>Create a function in one of the javascript files you always load. You may do it inline, but the function in the file makes it easier to change. My guess it should survive absence of the Wicket too. </div><div><br /></div><div>AlertError here is the generic error function showing jQueryUI custom dialog.</div><div><div><br /></div></div><br /><pre>function tryRegisterWicketAjaxOnFailure(message) {<br /> if (!Wicket || !Wicket.Ajax) {<br /> return;<br /> }<br /> Wicket.Ajax.registerFailureHandler(function() {<br /> alertError(message, 0, 'center', true);<br /> });<br />}</pre><br /><div><br /></div><div><b>3.</b> As our tryRegister takes a <i>message </i>parameter we need to pass it from the Wicket. So, in your <i>BasePage.java</i> or whatever code just add </div><div><br /></div><div><div><br /><pre>add(new HeaderContributor(new IHeaderContributor() {<br /> public void renderHead(IHeaderResponse response) {<br /> response.renderOnDomReadyJavascript(<br /> String.format("tryRegisterWicketAjaxOnFailure('%s')",<br /> getString("ajaxCommunicationFailedMessage")));<br /> }<br />}));<br /></pre><b>4.</b> Just enjoy it. You may put 'refresh' button, or a spinner at this dialog which would constantly check if the network is back. It's up to your creativity and demand.</div></div>Alexanderhttp://www.blogger.com/profile/10093762646999402082noreply@blogger.com0tag:blogger.com,1999:blog-5866514577340267046.post-38796876105018099002011-12-17T13:57:00.002+02:002011-12-17T14:03:32.466+02:00Passing messages in method names? Why not!<span class="Apple-style-span" >Have been working with <a href="http://code.google.com/p/mockito/">Mockito</a> awesome mocking framework (i LOVE it). It also does use <a href="http://code.google.com/p/hamcrest/">Hamcrest</a> matcher as an option for matching its arguments. </span><div><span class="Apple-style-span" ><br /></span></div><div><span class="Apple-style-span" >So, say you don't want users of your library to implement interface directly but rather'd like force them to use the Base implementation of this interface and extend it instead? Putting away the reasons which led to this situation, here's how it may be accomplished:</span></div><div><br /></div><div><div><span class="Apple-style-span" >package org.hamcrest;</span></div><div><span class="Apple-style-span" >public interface Matcher<t> extends org.hamcrest.SelfDescribing {</t></span></div><div><span class="Apple-style-span" > </span></div><div><span class="Apple-style-span" > boolean matches(java.lang.Object o);</span></div><div><span class="Apple-style-span" > void <b>_dont_implement_Matcher___instead_extend_BaseMatcher_</b>();</span></div><div><span class="Apple-style-span" >}</span></div></div><div><span class="Apple-style-span" ><br /></span></div><div><span class="Apple-style-span" >Every time you'll try to create a direct implementation of this interface, you'll get this weird method which would tell you what to do. </span></div><div><span class="Apple-style-span" ><br /></span></div><div><span class="Apple-style-span" >Good or bad? To me rather bad; something is wrong in design if you offer interface but don't allow users to use it. On the other side it may be good, as BaseMatcher gives some bells and whistles and you don't always know about good base subclass. Also, this may have been caused by some external reasons. </span></div>Alexanderhttp://www.blogger.com/profile/10093762646999402082noreply@blogger.com0tag:blogger.com,1999:blog-5866514577340267046.post-32465416760813344812011-12-15T23:33:00.005+02:002011-12-16T19:29:22.075+02:00Wicket DownoadLink and AjaxDownload with non-ascii filenames<div><b>The problem - yet unsolved for me :(</b></div><div><b><br /></b></div>You have an Apache Wicket application (in my case, this is wicket 1.4.x). You have a page which asks user to download some content and then lets download it. Content is dynamically generated (file?). It should have a name (default one) on client's machine. Name may have cyrillic (or Chinese) symbols.<div><br /></div><div><div><div>Symptoms are well described here <a href="http://stackoverflow.com/questions/93551/how-to-encode-the-filename-parameter-of-content-disposition-header-in-http">http://stackoverflow.com/questions/93551/how-to-encode-the-filename-parameter-of-content-disposition-header-in-http</a><br /><div>Behavior and the way to overcome it are well described on <a href="http://www.codeproject.com/KB/aspnet/NonUSASCII.aspx">http://www.codeproject.com/KB/aspnet/NonUSASCII.aspx</a> </div></div><div><br /></div><div><b>Solutions</b></div><div>First of all, I was unable to solve this completely :(</div><div><br /></div><div>Coming from StackOverflow post, the good way to do would be to form the URL ending with a filename (URL-encoded), and show no filename in Content-Disposition header. All other tricks and tips work not well under different browsers.</div><div><br /></div><div>Wicket usual approach is to use either <a href="http://wicket.apache.org/apidocs/1.4/org/apache/wicket/markup/html/link/DownloadLink.html">DownloadLink</a> or <a href="https://cwiki.apache.org/WICKET/ajax-update-and-file-download-in-one-blow.html">AjaxDownload</a> (thank you guys for such a good solution! Liked it much). First of them is using usual wicket URL coding strategy and second - pretty much the same, being a AjaxBehavior and thus IBehaviorListener. That far I could see no real way to change these URLs. The issue is that both of those don't allow for custom URLs, they are actually plugged into Wicket's infrastructure of page-component-iBehaviorListener-RequestCycle-RequestCodingStrategy chain, so we don't have direct control over it. </div><div><br /></div><div>One solution proposed by Martin Grigorov on the wicket-users mailing list was to use </div><div><div> <a href="http://wicketinaction.com/2011/07/wicket-1-5-mounting-resources/">http://wicketinaction.com/2011/07/wicket-1-5-mounting-resources/</a> for mounting, but that did not work out for me as I needed to use containing page's model to generate the actual data. </div><div><br /></div><div>Fail :( </div><div>Will up if any luck.</div><div></div></div></div></div>Alexanderhttp://www.blogger.com/profile/10093762646999402082noreply@blogger.com0tag:blogger.com,1999:blog-5866514577340267046.post-87536882973886717042011-12-15T22:17:00.002+02:002011-12-15T22:18:25.289+02:00Wicket this timeanother incarnation, switching to wicket-related posting as we're doing wicket jobs at the moment. <div><br /></div><div>Hopefully experiences shared here would save someone's time -- that's a good enough reward.</div>Alexanderhttp://www.blogger.com/profile/10093762646999402082noreply@blogger.com0tag:blogger.com,1999:blog-5866514577340267046.post-10938668145800444112011-02-18T22:04:00.003+02:002011-02-18T23:00:51.776+02:00Java SFTP server review - current stateThe life goes on, the new tasks emerge and new research challenges appear. <div><br /></div><div>This time we got the 'heritage' - strangely coupled old system with unclear signal paths <span class="Apple-style-span" >(write/poll filesystem instead of doing a local notification call)</span>, weird predicates<span class="Apple-style-span" > (the file is considered uploaded as soon as 1 hour passes from the start of the upload) </span>and really bad heterohenous design. </div><div><br /></div><div>The target of the system is get some files uploaded via SFTP (SSH File Transfer Protocol) protocol and process them with some rules, producing output files and making them accessible via the same SFTP. As most of the system is written in Java, we decided to try find the Java SFTP Server to replace part of the existing system. Good things about such an rearchitecturing:</div><div><ul><li>Making signals simple.</li><li>Having control over filesystem, clients and authentication.</li><li>Introduce uniform build and deploy procedures for the whole system.</li></ul><div>A little trouble is that one should distinguish between SFTP and FPTS (FTP over SSL) protocols, as they are completely different. </div><div><br /></div><div>Having all that in mind, with the good mood we started our little research. Found out some libraries:</div><div><ul><li> <a href="http://mina.apache.org/sshd/">Apache Mina SSHD</a>. Sister project of the <a href="http://mina.apache.org/ftpserver/">Apache FtpServer</a>, this one looks really good in terms of the object design and operation. Code is yet a little fresh, but object breakup is really awesome. We collected our server with the Spring beans and that was pretty easy - to replace the key provider, specify key storage, authenticator and more more other things.<br />If you don't want to bother configuring it yourself, the factory gives you pretty good result as it is.<br />Being a generic SSH server, Apache SSHD is capable of running SCP and SFTP. Unfortunately, SFTP support is now outdated, and supports only the protocol version 3 (current is 5 or 6). :( We could not use it for the project, as for us it is crucial to have WinSCP support in, and that does not work with protocol v3. After asking about new version guys on the mailing list told me that it'd be awesome if someone implemented that. Who knows if I have some free time, why not? :0<br />License is strict <b>GPL</b></li><li><a href="http://sourceforge.net/projects/sshtools/">SshTools</a> is another implementation of the same. Has declared support of the SFTP, SSH and lots of other stuff. Designed pretty good too, has also notion of virtual file system which is very useful if one needs to move storage to DB or process files on the fly. On the other hand, has few documentation and is also licensed under <b>GPL</b></li><li><a href="http://javasecureftpd.sourceforge.net/">JavaSecureFTPd</a> the project is dead as the stone is. <b>GPL</b>, but no one cares :)</li><li><a href="http://www.sshtools.com/en/j2ssh-maverick/">J2SSH Maverick</a> commercial; we did not ever try it, but the rumor says it is pretty good. Has all necessary protocol support.</li></ul><div>So, for now situation looks following way - if you have a java app and need to embed SFTP server functionality to it, you either need to try SshTools, help Apache SSHD with the new protocol ;) or pay money for the commercial one. </div></div></div><div><br /></div><div>Not yet sure what we stick to...</div>Alexanderhttp://www.blogger.com/profile/10093762646999402082noreply@blogger.com5tag:blogger.com,1999:blog-5866514577340267046.post-51941982201759211632011-02-04T11:27:00.002+02:002011-02-04T11:29:11.565+02:00Reviving for the second timeFinally, the time has come.<br />I'm about to change job.<br />I'm about to change an occupation to something a little different.<br /><br />Got a new laptop to support my new activities while on the go :) got a new passion and new belief in all the good.<br /><br />Hopefully will finally establish this blog posting the way i wanted to originally -- one technical posting a week. Think i'll have pretty much of stuff to write on.Alexanderhttp://www.blogger.com/profile/10093762646999402082noreply@blogger.com0tag:blogger.com,1999:blog-5866514577340267046.post-37434140102843634812010-07-01T11:01:00.005+03:002010-07-01T11:06:32.312+03:00Download all java older releasesOk, i know that at least once in the life java programmer has to download jdk 1.3.0_u03 to reproduce the old, freaky and disturbing issue on the legacy system.<br /><br />Because we need to support this system.<br /><br />Searching for such a download main be a pain in the butt, unless we know the magic url - <a href="http://java.sun.com/products/archive/">http://java.sun.com/products/archive/</a><br /><br />Yes, I know that's no more Sun, but it anyway allows you to download specific versions of JDK, JRE and other stuff! Which is really useful for real-life experience.Alexanderhttp://www.blogger.com/profile/10093762646999402082noreply@blogger.com0