Maschine 2.0 Newbie Review

It has been some time since I upgraded my Maschine to 2.0. Not a big win for me when I think about it, but you know how it is – old Maschine will hardly have any support and – probably the biggest reason – I wanted to support Native Instruments and maybe get some more sound content in the process.

I used Maschine 1.x with my Maschine Mikro (Mk1) to create a few songs – or mostly just drum/bass lines for songs that we could perform live. It was alright and I liked that I needed to interact only with the controller on stage.

Now I tried to use Maschine 2.0 expecting some improvements over the previous software version. I’m sure many people got what they wanted, but for me Maschine 2.0 is more like a facelift – without bringing anything essential. Kinda like “we have to come up with something new” stuff. This is probably not fair, but I just use basic things and I feel that way.

I don’t expect things to always go my way. I have ideas and try to communicate them on forums of my favourite products, not to mention many bug reports for things like IntelliJ IDEA that even got fixed. ;-) One simply cannot have it all. But there are a few things that are kinda striking.

I use Large layout for instance and let’s take a look, how it looks by default:

First the “red problems”: So the Arranger (upper part) does not display all 8 groups you have (at least by default), and Pattern Editor has plenty of free space for more sounds than necessary. Of course you can use this space in the part with Piano roll…

However, the biggest point here is – even though you can change the layout (use the section corner marked on the right of the screenshot) there seems to be no way how to save it. So even if you change it, the next time it’s gone.

My other issue was with zooming. You can only zoom on the zooming scroll bars (horizontal ones are marked with blue, but the same goes for vertical ones). Now imagine you want to fix a particular event with your mouse. To zoom to any reasonable level you have to go away from the event (that is already probably selected) and meddle with the scroll bar, pressing the mouse button, moving the mouse up/down to zoom – and also to the left/right in order to keep the event in the view. Now imagine using just Ctrl+mouse wheel right on the spot (or Ctrl+Shift for vertical zoom which is less needed in most cases). Wouldn’t that be great?

Generally many things in Maschine UI are made in a way that is completely counterintuitive – the only way is to learn the stuff and keep using it, because otherwise you have to refresh it every time before you occasionally use the Maschine software (my case).

When I compare this with Reaper for instance, that is a true power tool where:

  • you see keyboard shortcuts next to the action in any menu (main, contextual) – this is true for main menu in Maschine as well, but that is just too little
  • you can assign nearly whatever to whatever in their Actions window – not to mention you can use it as a quick reference and find the shortcut for an action there too
  • UI always loads how I left it
  • there are tooltips for buttons, often even with status information (for instance: Metronome disabled) – tooltips would be a big help for any starting/intermediate/occasional user of Maschine

We may argue that focus in Maschine is on another thing (partially true), that they don’t want to spoil it with too many DAW-like features (agreed, mouse zoom is not colliding with anything in Maschine though), and that you should mostly use their hardware. The last thing is valid for things like live productions (and more of course), but one way or the other – if you prepare something in Maschine for later use, you may need to edit it. And that is much easier with UI and mouse.

To sum it up: Maschine UI is different from standard even when not necessary, lacking tooltips completely, there is no in-place help with keyboard shortcuts, few contextual menus (no wonder when right-click deletes stuff, double click would probably did just as good), it doesn’t save the UI layout, zoom is awkward and I’m not going into shortcut customization.

I know that UI is just an addition to the hardware (though absolutely necessary) and personally I can pardon that you can’t change keyboard shortcuts. But many of these things are kinda easy to fix (tooltips?) and they would help a long way – especially users new to NI.

Maschine sure is a lot of fun anyway, but a little bit more seriousness to its DAW aspects wouldn’t hurt at all.

Witcher 2 bittersweet review

I’ll not bother with pictures or story, everything can be found elsewhere. I used http://witcher.wikia.com/ as a guide when I needed it. I want to sum up my experiences and feelings from the game development lately.

Consolization is obviously unstoppable process that can be understood. Some games deal with it better – with PC having proper treatment – others fare worse. Witcher 2 is the latter case, unfortunately.

I’ll skip all the good parts – story and graphics (after many years I upgraded my graphics adapter to get this game into enjoyable shape :-)).

The first big letdown was the fact that keyboard is adjustable only out of game through dedicated configuration program (as are many other things, but those are of less importance for serious gameplay). Even when you want to check your layout, you have to go there. My solution was to use snipping tool and let the screenshot on the second monitor as a reference. So it all started with terrible customization experience. If you want to change some setting be ready for 5 minutes roundtrip.

In-game control of the character itself is another disappointment. Geralt is unresponsive, walk is slow and then run is too fast when you’re picking things around – the whole feeling is laggy. Maybe it is my older rig, I don’t know. While turning around is acceptable, movement itself is terrible however.

I don’t like new fight system, first Witcher was more fun with combos. I avoided bombs and traps, unless situation required them (the first wraith fights especially). Maybe one of the reasons why I did so was that the whole UI was laggy, unresponsive and workflow terribly designed (graphically it is alright).

Similarly, mini-games that worked in the first game clearly suck in this one. Fist-fight is for babies, arm wrestling on the other hand is just frustrating with that jumping cursor – and dice poker? They couldn’t mutilate it any more (camera view, post-processing, physics, everything).

I don’t know what happens on the background when I move around my Inventory, but mouse is very lazy. Sorting the stuff is all but intuitive, with no tooltips where they would really help. And you have more ways how to accept things – mouse click, Enter (but not the numpad one?!) and Space. But not all of this works everywhere. I’d  welcome escape for dialogs with shopkeepers (it gets you menu).

Dialogs control are terrible too. You can believe clicking with your mouse on a dialog selection, but while the other one is highlighted, it is also the one to be selected. You have to move your mouse first – how practical. So you decide to load previous save, so you can repeat the dialogue. But saved game often shows picture from some completely different save – you can see the time is right (few minutes ago), but it truly is misleading when you first notice this. Audio is not balanced at all either – sometimes everything is fine, then other dialogs are hardly audible – you just don’t know how to set music volume properly.

Because so many things are made so complicated in game thanks to the controls (probably not a problem on console) I just didn’t do them. I made minimum of alchemy.

Yeah, I played on easy – which I normally don’t. I did it because before upgrading my graphics card it was pain to go through tutorial fights even on lower resolution. Game is probably CPU bound in my case, though new graphics definitely helped a lot. Maybe I would have to do more of alchemy on some higher difficulty, but honestly – I imagine it being rather frustrating anyway. I liked (or at least used) alchemy in the first game a lot. Not here.

Graphics and story are the strongest point for me. Audio is OK when it comes to soundtrack (I liked first one much more and often put it on without the game), dialogue quality varies (especially timing and volume during other noise), shouts are mostly hardly believable.

When I compare this game to Mass Effect (1 or 2, never played 3) – that is if you like both genres – this one was far less enjoying. In Flotsam I was stuck like forever, then the game got some pace, Vergen was OK, but all those corridors made me thinking how great freedom we had in the first Witcher – and chapter 3 was over very quickly. After this they tell you to wait after the credits to see the end… Don’t even bother – they go for like 20 minutes or more? Just check it on YouTube. Mass Effect? I just sat back after the job well done (saving the galaxy after all) and I could just listen to the music. Credit music in Witcher 2 gets boring after all those letters.

I’d gladly sit back and watch the credits, I’d really do – but after over 5 minutes it just adds bitterness to the bittersweet taste of the whole experience. Shame – could have been nice 9/10. For me all in all it’s more like 7/10.

Git Bash Here in Console2 in Total Commander with keyboard shortcut (hotkey)?

Not sure whether I ever made longer title – but as I had to Google a lot about it and even wrote to Total Commander support email I decided to put it “on paper”. I wanted to press a keyboard shortcut to open Git Bash in Console2 (default window is just as terrible as “cmd”, marking, copying and pasting is just pure pain). Of course in current directory.

Because I have installed Cygwin as well and had it as a default shell for Console2, I decided to add a new tab configuration like this:

Main menu: Edit-Settings-Tabs-Add and then fill up things accordingly

Now the Total Commander part. While I googled a lot how to assign my custom command to a shortcut (hotkey) maybe I used different keywords, maybe I was just unlucky… I wrote to support in the end. Answer goes as this (thanks to Christian Ghisler):

  1. Go to menu Configuration – Options (you can get here with Alt-O twice) – Misc (last option in the list on the left)

  2. Choose your hotkey, I went for Ctrl+B (it doesn’t make any file “bold” I hope)

  3. Click on the small magnifying glass

  4. Click on usercmd.ini (all the way down)

  5. Click on New

  6. Choose a name, e.g. em_git_bash_here

  7. Click OK

  8. Enter the details (see lower)

  9. Click OK in all open dialogs

Here is screenshot of the settings in Total Commander:

Here the -t obviously chooses the tab you want to open and -d sets the initial working directory.

BTW: The last dialog is the same like for a custom button. I actually found a blog about how to add a custom button with Git Bash Here, but assigning it to a hotkey was another story. Also running it in Console2 was easier than it seemed from various internet resources. Many advices pointed to the Windows Registry – but I didn’t want that.

Total Commander itself is a bit tricky. Don’t get me wrong, I love it and that’s why I have bought it (way too late, but I have) and also could appreciate support (right to the point). But when you want to find that %P is “current directory” you better google it. Ctrl+F in the Help window (very good one actually) does not help, because “source path” does not contain neither “current” nor “directory” obviously. :-) With Internet at hand these are no problems at all.

BTW2: If you have your command in Total Commander named you can just reference it when you need it for button bar – don’t click on magnifying glass icon, just set Command value to “em_git_bash_here” (or however you named it) and you’re done.

Hope you made it with my procedure and my pictures. May the power of keyboard shortcuts (or hotkeys, whatever ;-)) be with you!

ZSE Ponuka E.Zľava?

This time in Slovak about how I was awarded 0% discount from my electricity retailer. Sorry for being silent lately, I have a lot of work and no steam to write here right now.

S neodolateľnou ponukou E.Zľava od svojho seriózneho dodávateľa ZSE (člen skupiny e-on) som sa prvýkrát stretol, keď nám ju poslali poštou. Keďže v nej išlo aj o nejaké asistenčné služby a navyše viazanosť, nebol som si istý, či ju chcem – takže som ju jednoducho neriešil.

Lenže potom som raz dostal návštevu, ktorá mi to všetko vysvetlila. Asistenčné služby sme nechceli, ale zľavu za viazanosť… povedal som si, keď už je chlapík tu, prečo nie. Veci mi boli vysvetlené, ale z mojej strany išlo aj o istú mieru dôvery, keďže som jednal so spoločnosťou, ktorej zákazník som už nejaký čas, bla, bla, bla.

Chlapík odišiel, ja som vyrazil na web – a ľaľa ho, aj takéto články som našiel:

Tak som sa podujal, že im napíšem, a tentoraz to bolo od srdca. Odpoveď som od 5. januára nedostal.

Vážená ZSE

Elektrinu od Vás odoberáme už vyše 6 rokov a nemal som v úmysle na tejto skutočnosti nič meniť. To sa všetko zmenilo počas uplynulej hodiny.

Dnes sa u mňa zastavil zástupca vašej spoločnosti, pán G. (Gxxx? Gxxxx? ťažko to rozlúštiť) ohľadom E.Zľavy. Ja som hovoril, že sme neporozumeli celej ponuke na asistenčné služby, ktorá nám už skôr prišla – bola pre nás krajne neprehľadná. Váš zástupca túto vec neriešil, išlo len o ponuku zľavy. Celú dobu sa hovorilo o 4%, chvíľu som to študoval, ale zase som nechcel veľmi zdržiavať.

Myslel som si, že ZSE je totiž seriózna spoločnosť. Váš zástupca o.i. povedal aj to, že ak by som aj prestúpil inam (čo som neplánoval), tak by som prišiel len o zľavu. Toto neviem potvrdiť, keďže dodatkom sa upravuje doba platnosti pôvodnej zmluvy na dobu určitú a musel by som zrejme podrobne študovať aj tú, čo by skoršie ukončenie znamenalo.

Vrcholom všetkého je, že sme rodina s dvomi deťmi v 4-izbovom byte, varíme na elektrike takmer každý deň (malé deti) a naša spotreba je pod 3MWh, čo znamená (ako asi viete) 0% zľavu. Aj pri 4% by som ušetril možno 3 eurá, keďže ide o 3 mesiace (čo zástupca zabudol pripomenúť), aj to nie z celej sumy (na to našťastie upozornil).

Takže kvôli možno 3 eurám (v mojom prípade 0) ma zástupca “serióznej” spoločnosti musí otravovať osobne doma, vysvetlenie dopadov zmluvy zďaleka nedostahuje kvality podpriemerného poisťovacieho agenta a navyše mám teraz zmluvu na dobu určitú, pričom predtým som sa o ňu nemusel a NECHCEL starať.

Reči o tom, že “asi len zisťujú, aký kmeň im ostal”, alebo odpoveď na otázku, prečo nemôžu zľavu prosto len tak priznať v zmysle “obchodníci nemajú prístup k osobným údajom”… už tu som mal začať tušiť problémy. Len kvôli značke ZSE som to podpísal, alternatívneho operátora by som vyhodil dávno, alebo by som si pred ním išiel na Internet vyhľadať názorové články o jeho serióznosti.

Takto si dávam do kalendára na december poznámku, že sa treba poobzerať po inom dodávateľovi elektrickej energie. Možno by som si to rozmyslel, keby ste mi originál môjho dodatku doručili späť a najbližšie ma otravovali s niečím, čo mi naozaj ušetrí peniaze. Takto totiž naopak iba plytváte mojím časom, o trpezlivosti nehovoriac.

S pozdravom

Richard Richter

zák.č. xxxx

Trochu ma to celé prekvapilo, keďže – hoci na Slovensku – na mňa ako už existujúceho zákazníka podobné finty zatiaľ neskúšal ani žiadny operátor internetu či telefónie, ani moja banka, proste nikto.

Mimochodom, dnes už ponúkajú 4% od 2MWh ročne, čo by sa nás už týkalo. Ale nič to nemení na fakte, že ide o jednotky Eur. Takže nechtiac, ale predsa, budem musiet koncom roka riešiť nejakú zmluvu na energiu. A nevidím dôvod, prečo ju zase riešiť so ZSE.

Happy New Year 2013!

Happy New year, of course! My last year was a bit poorer blog-wise. For some reasons I was more lazy to write about things. Heck, sometimes I think that I was less lucky with new technology in overall. I achieved some nice results with testing in our company during the previous year. This year I wanted to push Continuous Integration, testing a bit further, maybe Gradle – but results in CI area are mixed and the rest brought no real results at all.

On the brighter side, I managed to finish my quest for system time shifter on JVM that would be usable for testing purposes – all documented in my post. Blogging is not all of course and I am quite happy how topics around Clean Code got some attention around me. We pushed Java Simon project a bit further too, I learned a few interesting things around Spring, MVC and jQuery… Add this beautiful Scala class on Coursera and this year was more than fun after all.

Still I’d like to make some resolutions. I discovered QueryDSL (thanks to a colleague of mine) and this seems to be answer to readable and compile time safe Criteria – because those shipped with JPA2 are simply horrible to read. It works well with IDEA’s annotation processor, Maven and it should be no problem with Gradle either. Ah, Gradle! For around two years I’m watching this guy but for whatever reason I was not able to use it for anything more than a few tests – but that is not Gradle’s fault. I like it, I like the idea, I like the language – and I think this year is time to switch Java Simon from Maven to Gradle. And after that I’ll go on with projects in our company, although the battle there will be more difficult I guess.

Out of technology, I managed to put together a few songs with my colleagues and it was fun – the first time I played in something close to a band. We played only on our company party but it doesn’t change anything… it was a real fun. We didn’t have a drummer so I used my Native Instruments Maschine Mikro and pre-programmed our songs – and I was really happy with the results. I’ll probably dedicate a post to Maschine Mikro, because it is one really interesting controller (and software too!).


Maschine Mikro controller

Talking about music, I managed to upload two full-blown tracks to my Soundcloud and later added two simple guitar+voice tracks. While mixing/mastering is still my weakness, I’m happy that I was able to pull through this recording-wise. And just how I imagined – my songs composed with paper, pen and acoustic guitar many years ago can really work as rock recording too.

So what about this year and those resolutions? Gradle – sure. More testing methodology on our projects – maybe I’ll even manage to document it here on the blog. Pushing Continuous delivery just a bit further again. Scala or other JVM language? I don’t know. Maybe, maybe for tests. And a bit of my music – I need to practice more with keyboard, guitar and bass guitar (yeah, I bought lovely Yamaha bass too).


Bass guitar Yamaha RBX375

Last resolution is no resolution at all – we have to survive somehow “socialistic” experiments of our government here in Slovakia (although there is nothing social about them). Europe has its own deal of problems – and USA? Well they saved themselves from falling down that fiscal cliff or what – just a few hours ago. And it probably means to make the cliff a bit higher for the next time. So we might have escaped one Doom’s day lately at the end of 2012, but who knows how our civilization will fare in the future.

Then I remember those really poor and I know we have nothing really horrible to complain about. So once again – Happy New year – and whole year of 2013!

My last two years with technology

I’ve been quite busy lately – hence the pause in my blogging. My last post was very specific Java related article, today we’re going to do something lighter – a little whine about various devices, gizmos and maybe even software/services I’ve encountered during the last two years. While generally I love our age for the current level of technology, sometimes I’m desperate seeing unnecessary flaws, often just software ones – and these can seriously affect the final experience. However, today I decided to add a lot of good examples, too, and every case should be short (though I’m bad at keeping stuff short ;-)).

BTW: Now I see that this is actually sort of continuation of this post.

Phone case: HTC One V

I like Android phones in general. And I like both my Wildfire and One V – however they both have quite funny flaws. Wildfire’s display is unresponsive when I pull it out of my pocket while ringing (that’s why I call back my friends right after I can’t pick them up) and One V – for a change – is very quite in-call. In both cases those are quite crucial phone related issues – and in both cases many people observe the same (but not all). Other than that – on Wildfire (2.x Android) I liked that default HTC clock application showed time of the next alarm and this view was removed from newer OS. Of course One V is faster and better in overall, but still… 3 out of 5 stars. Both.

Partition case: EASEUS Partition Master Home Edition

I wanted some free legal replacement for Partition Magic – and I found this. It may not be all-powered tool for every thing around partitions, but it did anything I wanted and so far never failed. Partitions smaller or bigger? Merge partitions? (Here it actually needs enough space on the partition you are going to merge to for all the files from the other partition – but that’s rather a non-issue.) System copied to my new SSD disk? No problem. Using Windows repair process took much longer after that. ;-) 5/5! For free? Yes!

Disc case: SSD drives (Crucial M4 in my case)

Talking about SSD – well, technically it is indeed non-disk, but you know how it goes. SSD generally is fast, of course, but also cheap enough nowadays – so to put there your system volume at least is a really good idea. I did so and my computer runs and starts programs much faster. This is currently probably the best boost you can get for your money. CPU or memory or GPU? Phew… SSD made my computer fleet-footed. I can’t say more really, I somehow decided one day, checked the prices, cross-referenced all the new names for me (like Crucial, never heard of them before!), reviews were good, so I bought this one. And I’m not even having SATA3 on my mobo. 5/5

Java case: Spring JdbcTemplate

When I can I program against standard APIs – like JPA2 instead of Hibernate. When I can. Sometimes you need to go through the select cursor-style and while I could use underlying Hibernate, I decided to go straight for JDBC. And I wrote all the code. With ifs and wheres and parameters. After a couple of hours, I was done, piece was tested and then it hit me! “Man, there is supposed to be that Spring class making it much easier!” JdbcTemplate made the job, I didn’t have to write my ifs twice (first to get the query, then the parameters again), all the exceptions were handled for me and there was even every case you could think about how to process the result set (in my case callback for every row of it). This is how I like stuff made. Documentation clear… actually I mostly just let IDEA to offer me the choices and I made them right there the right way thanks to proper names. Love that. 5/5

JavaScript case: File download plugin for jQuery

Check what this plugin is about – and also its demo. Users sometimes want silly things like “can you disable the button after I press download…” (sure I can!) “…and then after download enable it again?” (are you crazy?!) But you can do it with this plugin based on hidden iframe and a cookie. I had to adjust it a bit because I had a corner case (but quite common) that there were no data and no download, which is third case from user’s perspective in addition to success and (server) failure. I’m no JavaScript expert, on the contrary – but I fell in love with jQuery in the process. And however silly HTTP is for delivering applications, things like jQuery and this plugin make it more bearable (though HTML5 and things like WebSocket mend a lot of my 10-year old concerns). For this plugin and the whole idea – 5/5.

Command-line case: GNU tools for Windows – GnuWin

I never liked all that CygWin heavy-weighted stuff, but GnuWin packages made my day. I just installed them, added c:\Program Files (x86)\GnuWin\bin into my PATH (they all go to the same dir, luckily) and stared cmd just to enjoy grep (package grep), awk (gawk), ls (and many more in coreutils), zip/unzip/gzip/tar/bzip2 and of course sed! Mentioning typical Unix/Linux tools – you may also like (not related to GnuWin) vim, though I’m happy with notepad2 for most cases (read second half of this post). But you never know when you need vim’s macros. But yeah, these are not really command line tools in Windows. GnuWin packages definitely are and they deserve 5/5 for making my life easier.

Windows environment case: Rapid Environment Editor

After so many times heading into System, Advanced, bla-bla, setting the PATH in that super short line I realized “there must be a better way and someone must have already fixed this”. Yes, they have – with Rapid Environment Editor. Adding new paths with this tool is just so much better, it checks whether the path is valid – even with other variables you are referencing (if those are paths, like JAVA_HOME for instance). No more needs to be added: 5/5

Corporate tool case: Planview

For me Planview is just a tool to report my hours. I don’t use its powerful project management features. And every time I need some report out of it I don’t understand the language it is speaking to me. This tool one of those tools forgetting that they are not my only primary tools I use. Honestly, I openly hate it. Terms out of other world, a lot of misuses of the application (not only mine actually), tons of discussion how we should use it – and still we’re not using it the right way. Personally – I blame the tool. I can use Jira, Confluence and many other tools without any problem, but Planview is simply killing me. 1/5 (and yup, it’s IE only)

More-than-a-mail case: Lotus Notes

Lotus – I think this is love or hate thing, but however defended by people who like it, it is still viewed as pain by the vast majority of users. My Lotus for instance doesn’t display mouse cursor in mail editor when it’s not focused window, wrongly shows which tab is selected when two are opened at once, pastes Excel tables is as image by default and there are many other silly defaults. Date you see in trash is trash date, not the date of the message? You can’t reply to mail in your sent mail?! My contacts get often screwed by some cashing I don’t understand and don’t care at all. Not to mention it doesn’t look like normal Windows application (not that I’m a big fan of Windows, but still). Once a colleague closed Notes by accident and I just thought it funny to remark “see, stupid Lotus Notes” – just because whatever bad happens there is kinda Notes’ fault. I read people testifying how Notes rocks, etc. But these people live in the closed world of Lotus. Linux guys can hate Outlook, but it is really usable. Lotus? As a mail and calendar? Not a chance here… 2/5

Blu-ray case: Samsung BD-E6100

Recently I’ve got myself a blu-ray player (finally). I wanted Samsung, because my TV is Samsung, price was alright, I chose model with wi-fi, brought it home and after some initial scare (it didn’t play any disk first, I had to unplug it and after this kind of restart it was fine) I was happy about its performance, speed and everything, especially compared to our older DVD player (newer Philips luckily have remotes for common people too, not only for snipers). I managed to play content from computers (with Serviio installed, though SRT subtitles don’t work unexpectedly) and remote control provided four crucial buttons for TV (on/off, Source, volume up/down) – actually many of buttons from Samsung TV remote work as well (expected). After some time I decided to plug ethernet cable in though, because wi-fi often lost the connection to the router (our notebooks never have the problem, even from the same place). Even with ethernet most of the Smart HUB stuff is quite slow. In overall it was a big upgrade compared to DVD player and I was actually surprised how well it works and plays. And Smart stuff? They still might upgrade it somehow and I didn’t buy it for that anyway. 4/5
Edit 2014:
I’d lower the rating to 3/5 after thorough experience. Compared to previous DVD player it does not continue where it ended when turned on again. Actually it does for files, but not for discs. Actually sometimes yes… but nobody knows when and why as it is not even consistent with the same disc. And sometimes it makes funny noises and is very slow with blu-ray discs. With too many of them to be the disc fault.

Conclusion

Not once I was thinking about myself as a “toiletologist”, because I just think too much about every single flaw of toilets as well. I never could understand why we – mankind – are unable to develop total toilet that always flushes everything, why we again and again put urinals so close together that you can use only 2 of 3 in the end, why we put toilet cubicles with legs on shiny reflective floor, not to mention various silly ways how to screw with automation of flushing, washing, drying or whatever.

Sometimes I want to scream “how could you do such a silly mistake?” But then I realize: “Man, it’s just software, it’s meant to be buggy (not that I agree that much :-)), the whole computer science is so much younger compared to the building industry – and look what they are able to do in a silly way every now and then. Not only on toilets, but when these are still not ‘debugged’ after all those millennia then what should we expect from the software, hm?”

The more I am happy for technology that really helps and doesn’t “think” that it will be the only thing I need to pay attention to. I have my own real life beyond technology too, after all.

Changing system time in Java

I always wanted to find some reasonable way how to tell JVM “hey, it’s 3:47 AM, January the first, 2000″. When you have a need like this you probably use some DateFactory pattern. People argue – “that’s the cleanest way, put it into the design!” However this comes with a price:

  • This cleanest way means to pollute your code on many, many places with your DateFactory – one place where a programmer forgets and you’re screwed. No need to mention how difficult to trace these problems may be, though they are not difficult to locate when you find out what the problem is – because there is only one place where new Date() and/or System.currentTimeMillis() may appear – in your DateFactory class. (Now when I think of it, I’d probably come up with a technical solution to force this pattern, some Java language aware analysis tool searching for exactly these two calls.)
  • This DateFactory may or may not be dictated by the requirements – real, inherent ones, not derived from technical needs…
  • …actually, in many cases you need to shift time only because of the tests.

When the application somehow implies DateFactory solution, so be it. There surely are systems where it makes sense. In my line of work, however, I messed with some kind of the DateFactory only because of the need to test the system on a specific date, or (in rare cases) to run some highly administrative feature as if it ran on a specific date. While the second case could be just right for the DateFactory, it wasn’t part of our main application code, but rather our migration/preparation/installation utilities and they were never run by the user. So if I had known about any other solution than DateFactory, I’d have gladly welcomed it. I hadn’t then.

Every single time this situation occurred I cursed JVM creators for not adding unified standard way how to mess with system time (guarded by security manager just in case), or some “java” command option, or whatever. My need arises again and again – especially during testing. It’s much harder to prepare time aware data (you have to generate/customize them every time) then declare “you run at this time!” Unless the second thing is impossible of course. But imagine you need to test specific billing job running on New Year’s Day. “Go for the DateFactory you moron!” Yeah, but imagine you have system with @Past annotation from Bean Validation framework. Guess how that one uses your DateFactory? Finally I got the idea – to mock it somehow. Mocking such a thing though is messing with JVM to a degree – as you will see later. Now let’s follow the story as it went…

Solution: jmockit

Actually – I wasn’t the first one. I found that other people wanted to use jmockit library to mock the system time. Jmockit is surely powerful library, more powerful than I can tell, because I actually (sorry to say that) suck in mocking. If you mock System.currentTimeMillis, you’re done (new Date() and all other ways to get the real time use this call). But how to mock this system static native call? Jmockit can do it, and it does it on the side of the callee – which means you don’t need to modify anything else – just set up the mock on the side of System class. During some troubleshooting I tried to use different mock libraries and different approaches, but unless I’m mistaken there are only two ways how to do it – on the caller’s side – or on the callee’s one. Callee is the right side, right? The same way how you have to pollute your code with DateFactory call, you’d have to enumerate, autoscan or whatever else your code in order to mock it on the caller’s side. No way to do this simply and completely when you think about dynamic class loading too and I bet you can throw many other problems on this solution. So I reiterate: *Mock the system time on the callee’s side.* (That is System class, obviously.) Jmockit can do just that.

First we need the class “overriding” currentTimeMillis – here it is (it can be nested class BTW, that’s why it’s static on my listing):

import mockit.Mock;
import mockit.MockClass;
...
   @MockClass(realClass = System.class)
   public static class SystemMock {
       /**
        * Fake current time millis returns value modified by required offset.
        *
        * @return fake "current" millis
        */
       @Mock
       public static long currentTimeMillis() {
           return INIT_MILLIS + offset + millisSinceClassInit();
       }
   }

And now we will use this class:

import mockit.Mockit;
...
           Mockit.setUpMock(SystemMock.class);

Done! From now on all time is changed for the JVM. Or is it? This solution actually has two problems. Let’s deal with the problem numero uno:

Problem 1: you can’t call the original currentTimeMillis

How can you base your shifted time on the real time, when you don’t have the original time now? It would be nice if you just could set the offset and your method simply returned non-mocked millis + the offset. Jmockit can mock the call, but then it is not possible to call the original method without the mock – not for static native calls. So if you use it, you’ll run out of stack in recursion gone wild.

Luckily since Java 5 we have System.nanoTime(). While nanoTime itself is not based on any real world time, we can still use it to determine the time since we set up the mock – if we remember what were nanoTime and currentTimeMillis before we did so – and it can be any particular time, for instance class initialization time:

   private static final long INIT_MILLIS = System.currentTimeMillis();
   private static final long INIT_NANOS = System.nanoTime();

Now it’s easy to tell how might method called from my mock method look like:

   private static long millisSinceClassInit() {
       return (System.nanoTime() - INIT_NANOS) / 1000000;
   }

The only thing you need to do now is to set offset in some meaningful way. I offer my whole solution wrapped in a class straightforwardly called SystemTimeShifter:

import java.lang.reflect.Method;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;

import mockit.Mock;
import mockit.MockClass;
import mockit.Mockit;

/**
 * Class changes the system time returned by {@link System#currentTimeMillis()} via JMockit weaving.
 * <p/>
 * Original System class can be restored any time calling {@link #reset()} method. There are a few ways how to specify modified system time:
 * <ul>
 * <li>setting ms offset via {@link #setOffset(long)}
 * <li>changing ms offset (relatively) via {@link #changeOffset(long)}
 * <li>setting new date, time or ISO date/time via {@link #setIsoDate(String)}
 * </ul>
 * <p/>
 * Any of these methods can be used through system properties (-D) this way (first property in this order is used, others ignored):
 * <ul>
 * <li>{@code -Dsystime.offset=1000} - shift by one second to the future (negative number can be used)
 * <li>{@code -Dsystime.millis=1000} - set system time one second after start of the era (1970...)
 * <li>{@code -Dsystime.iso=2000-01-01T00:00:47} - 47 seconds after beginning of the 2000, alternatively you can set only time (00:00:47, date stays current) or
 * only date (2000-01-01, current time) without 'T' in both cases.
 * </ul>
 * <p/>
 * There must be something that causes class load, otherwise nothing happens. In order to allow this without modifying the original program, one may use this
 * class as a main class with original main class as the first argument (they will be correctly shifted when served to the original class). If no relevant
 * property is specified via -D, nothing happens. In any case (programmatic or main class replacement) this class has to be on a classpath. For application
 * server usage this means it has to be in its system libraries, not in EAR/WAR that is not loaded during the AS start yet.
 * <p/>
 * Example:
 * 
 * <pre>
 * java -Dsystime.iso=2000-01-01T00:00:47 SystemTimeShifter my.uber.appserver.Main arg1 second "third long with spaces"
 * </pre>
 * <b>WARNING:</b> Sun/Oracle HotSpot JVM and its inline optimization may mess up with the mock after it is set up, so if you notice that the time
 * returns to normal after number of invocations, you should add {@code -XX:-Inline} option to your java command line. Other JVM specific options
 * may be needed for different JVM implementations.
 * 
 * @author <a href="mailto:virgo47@gmail.com">Richard "Virgo" Richter</a>
 */
public class SystemTimeShifter {
	/**
	 * System property setting ms offset.
	 */
	public static final String PROPERTY_OFFSET = "systime.offset";

	/**
	 * System property setting "current" millis.
	 */
	public static final String PROPERTY_MILLIS = "systime.millis";

	/**
	 * System property setting ISO date/time (or date, or time).
	 */
	public static final String PROPERTY_ISO_DATE = "systime.iso";

	private static final long INIT_MILLIS = System.currentTimeMillis();
	private static final long INIT_NANOS = System.nanoTime();
	private static long offset;

	private static boolean mockInstalled;

	@Deprecated
	protected SystemTimeShifter() {
		// prevents calls from subclass
		throw new UnsupportedOperationException();
	}

	static {
		String isoDate = System.getProperty(PROPERTY_ISO_DATE);
		String millis = System.getProperty(PROPERTY_MILLIS);
		String offset = System.getProperty(PROPERTY_OFFSET);
		try {
			if (isoDate != null) {
				setIsoDate(isoDate);
			} else if (millis != null) {
				setMillis(Integer.parseInt(millis));
			} else if (offset != null) {
				setOffset(Integer.parseInt(offset));
			}
		} catch (NumberFormatException e) {
			e.printStackTrace();
		}
	}

	/**
	 * Bootstrap main to allow time shifting before actually loading the real main class. Real
	 * main class must be the first argument, it will be removed from the list when calling the
	 * real class. Without using any relevant -D property there will be no time shifting.
	 * 
	 * @param args argument list with original (desired) class as the first argument
	 * @throws Exception may happen during the reflection call of the other main
	 */
	@SuppressWarnings({"unchecked", "rawtypes"})
	public static void main(String[] args) throws Exception {
		String[] newArgs = new String[args.length - 1];
		System.arraycopy(args, 1, newArgs, 0, args.length - 1);

		Class clazz = Class.forName(args[0]);
		Method main = clazz.getMethod("main", newArgs.getClass());
		main.invoke(null, (Object) newArgs);
	}

	/**
	 * Sets the new "system" time to specified ISO time. It is possible to set exact time with the format {@code yyyy-MM-dd'T'HH:mm:ss} (no apostrophes around T
	 * in the actual string!) or one can set just time
	 * (then current date stays) or just date (then current time stays).
	 * <p/>
	 * If parse fails for whatever reason, nothing is changed.
	 * 
	 * @param isoDate String with ISO date (date+time, date or just time)
	 */
	public static synchronized void setIsoDate(String isoDate) {
		try {
			if (isoDate.indexOf('T') != -1) { // it's date and time (so "classic" ISO timestamp)
				long wantedMillis = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss").parse(isoDate).getTime();
				offset = wantedMillis - millisSinceClassInit() - INIT_MILLIS;
			} else if (isoDate.indexOf(':') != -1) { // it's just time we suppose
				Calendar calx = Calendar.getInstance();
				calx.setTime(new SimpleDateFormat("HH:mm:ss").parse(isoDate));

				Calendar cal = Calendar.getInstance();
				cal.set(Calendar.HOUR_OF_DAY, calx.get(Calendar.HOUR_OF_DAY));
				cal.set(Calendar.MINUTE, calx.get(Calendar.MINUTE));
				cal.set(Calendar.SECOND, calx.get(Calendar.SECOND));
				offset = cal.getTimeInMillis() - millisSinceClassInit() - INIT_MILLIS;
			} else { // it must be just date then!
				Calendar calx = Calendar.getInstance();
				calx.setTime(new SimpleDateFormat("yyyy-MM-dd").parse(isoDate));

				Calendar cal = Calendar.getInstance();
				cal.set(Calendar.DAY_OF_MONTH, calx.get(Calendar.DAY_OF_MONTH));
				cal.set(Calendar.MONTH, calx.get(Calendar.MONTH));
				cal.set(Calendar.YEAR, calx.get(Calendar.YEAR));
				offset = cal.getTimeInMillis() - millisSinceClassInit() - INIT_MILLIS;
			}
			mockSystemClass();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	/**
	 * Sets ms offset against current millis (not against real, instead changes current value relatively).
	 * 
	 * @param offset relative ms offset against "current" millis
	 */
	public static synchronized void changeOffset(long offset) {
		SystemTimeShifter.offset += offset;
		mockSystemClass();
	}

	/**
	 * Sets ms offset against real millis (rewrites previous value).
	 * 
	 * @param offset new absolute ms offset against real millis
	 */
	public static synchronized void setOffset(long offset) {
		SystemTimeShifter.offset = offset;
		mockSystemClass();
	}

	/**
	 * Sets current millis to the specified value.
	 * 
	 * @param timestamp new value of "current" millis
	 */
	public static synchronized void setMillis(long timestamp) {
		offset = timestamp - INIT_MILLIS;
		mockSystemClass();
	}

	/**
	 * Resets the whole System time shifter and removes all JMockit stuff. Real system call is restored.
	 */
	public static synchronized void reset() {
		Mockit.tearDownMocks(System.class);
		mockInstalled = false;
		offset = 0;
		System.out.println("Current time millis mock REMOVED");
	}

	private static void mockSystemClass() {
		if (!mockInstalled) {
			Mockit.setUpMock(SystemMock.class);
			System.out.println("Current time millis mock INSTALLED: " + new Date());
			mockInstalled = true;
		} else {
			System.out.println("Current time millis mock probably INSTALLED previously: " + new Date());
		}
	}

	public static boolean isMockInstalled() {
		return mockInstalled;
	}

	/**
	 * Handy if you set up the mock by some other means like {@link Mockit#setUpStartupMocks(Object...)}.
	 *
	 * @param mockInstalled true if you want to pretend that the mock is already in place (or is/will be installed otherwise)
	 */
	public static void setMockInstalled(boolean mockInstalled) {
		SystemTimeShifter.mockInstalled = mockInstalled;
	}

	/**
	 * Returns real time millis based on nano timer difference (not really a call to {@link System#currentTimeMillis()}.
	 * 
	 * @return real time millis as close as possible
	 */
	public static long currentRealTimeMillis() {
		return INIT_MILLIS + millisSinceClassInit();
	}

	private static long millisSinceClassInit() {
		return (System.nanoTime() - INIT_NANOS) / 1000000;
	}

	@MockClass(realClass = System.class)
	public static class SystemMock {
		/**
		 * Fake current time millis returns value modified by required offset.
		 *
		 * @return fake "current" millis
		 */
		@Mock
		public static long currentTimeMillis() {
			return INIT_MILLIS + offset + millisSinceClassInit();
		}
	}
}

I’m not suggesting it’s a masterpiece of engineering – but it works pretty well and you can set up the offset in many handy ways (just the date/time, both, offset in ms, you name it), you can use it as the main class before you start some other real main class (this way I started the whole application server in completely different time – Weblogic 12c in my case, but I think it doesn’t really matter). But I did mention two problems, right?

Problem 2: After some time the time returns to normal!

This problem quickly manifests on Sun’s JVM (can’t tell about others) and I found this non-solution: http://code.google.com/p/jmockit/issues/detail?id=43

At least originally it was no-go for me as the suggested solution was -Xint – using interpreted JVM. This made tests unbearably slow, nobody would run them! I felt I’m pretty close to the solution and thanks to Rogerio Liesenfeld (jmockit author) and my private conversation with him above this issue I got pushed into the right direction. Sure, first I tried other mocking libs, but then I got back to jmockit (because it mocks the target, not the source of the call) and I tried again. I focused on what Rogerio wrote in his comment #7 (which was actually his reply to my mail). “So OK, if it’s HotSpot optimization, can’t I disable just that one? Even for that single class?” While I could not disable it for the class with Sun’s HotSpot (and I don’t know if it is any problem at all on different JVMs) I could disable it globally with -XX:-Inline. And yes, it’s much much faster than -Xint. Generally it should not be much slower than 1.5x of normal run with inlining – this depends on many factors of course (on overall “inline-likeness” of your application/test), but it’s much better than typical 10x penalty for interpreted JVM.

Problem 3: TestNG integration

Ok, I lied about two problems only – but only because this one is beyond the system time shifter itself. This problem was caused by my lack of understanding of jmockit and its interaction with TestNG. I wanted to shift my time for the whole TestNG suite without realizing that jmockit/TestNG may have their own agendas too. I tried to run my code with @Before/AfterSuite setting up my mocked time with SystemTimeShifter.setIsoDate(…) call and tearing it down again with reset(). But it didn’t work inside the test methods anyway, because something uninstalled my mock before the test method was run. Cedric from TestNG told me it’s jmockits business and Rogerio told me I’m using it the wrong way because it was never meant to be run this way for the whole Suite. I could use it around class or even method call, but I didn’t like the idea of time being shifted to the same point for every single method. I didn’t like the idea, that I can’t tell from log files how long the test is running (though the log file times were shifted too, I hope you don’t mind :-)). Silly on my part, however, this should work for you just fine:

   @BeforeSuite
   public final void setupSystemTime() {
       SystemTimeShifter.setMockInstalled(true); // because of the setUpStartupMocks further, which sets up the mock
       SystemTimeShifter.setIsoDate("2011-10-14T10:00:00"); // this set's the offset - but doesn't set up the mock (thanks to the assert above)

       // this line performs all the suite scope magic
       Mockit.setUpStartupMocks(SystemTimeShifter.SystemMock.class);
   }

   @AfterSuite
   public final void resetSystemTime() {
       SystemTimeShifter.reset();
   }

While technically the AfterSuite part is not necessary, it is cleaner this way. Jmockit uninstalls his part by itself, but time shifter doesn’t know about it. This way it got reset as well.

Conclusion

There it is – not perfect and not without little hassles (-XX:-Inline namely), but working fine so far, at least for my cases. In my eyes – this is really tragic fault of the current JVM date library, fault that cannot be mended easily. System.currentTimeMillis is the only relevant source of real time and unless we can mess with it somehow in a clear way we will always have need to mess with it in ugly ways. This reminds me of the t-shirt I have. There is a stargate like ring on it, it is just named “TIME GATE” – and Java Duke comes out of it, opening the future for us. I’m curious a bit how he could do it. Did he cheat on JVM somehow too? When will we have clean solution that makes any DateFactory rather obsolete? Will we ever? Or do we have to unlock the future with TimeShifters in such obscure ways? Java, Java…

Let me know your story with system time cheating. I know I haven’t talked about setting the computer system time. That is simplest solution for many occasions, but not for running the tests on Continuous Integration server shared with many other projects, so I just omitted this altogether. If you have any success story with SystemTimeShifter, if it helps you somehow, please, be so kind and let me know to lift up my spirit. :-)

Follow

Get every new post delivered to your Inbox.

Join 213 other followers