Wednesday, August 25, 2010

Automating with Winscp

If you find yourself working on windows in a mixed unix/windows development environment, you probably need to copy files from a unix computer.
You might even need to do this periodically.

In these cases, winscp is your friend - while using the winscp commands

Today I decided to dump a remote Mysql DB and upload it locally.
There are several ways to attack this issue :

  • remotely create the dump


  • create the dump locally and copy it
  • create the dump locally, and upload it to your computer remotely. 
  • This option is quite nice since you can always control the access to your DB and configure it for remote access. 

  • Even if both DBs have remote access, you might still want to dump and load the DB locally and that's due to the fact that these operations lock the DB, in large quantities of data you might want to shorten them as much as possible, thus settling on local operations.
    The lock will minimize, but the overall time will remain the same as you still need to copy the file.

    Dumping remotely


    Using 2 commands in a batch file like this :

    mysqldump --add-drop-database -u username -psecret -h 123.123.123.123 -B db1 db2 > temp.sql
    mysql -u root -psecret < temp.sql
    
    will generate a temp dump file and inject it locally. however, you can only use this in case mysql is configured with remote connect. In other cases, you will need to dump the file locally, copy it and then inject it.


    Automating local dumps with WinScp
    write a file called "my_dump.winscp" and write something like
    option echo on
    option confirm off
    open guy:secret@123.123.123.123
    pwd
    cd /tmp
    lcd %TMP%
    ! mysqldump  --add-drop-database \-u username \-psecret \-B db1 1> temp_dump.sql
    ! test \-e temp_dump.sql && echo yes 
    get temp_dump.sql
    rm temp_dump.sql
    exit
    
    then run the winscp commands like this
    winscp /script=my_dump
    
    The script above does the following
  • login
  • go to temp dirs remotely and locally
  • dump db1 to file
  • copy output file locally
  • exit

  • troubleshooting

    White writing the script I encountered several problems. The most important one is while writing the mysqldump command I got "Unknown switch 'u'.". I later discovered this is due to the fact the winscp needs switches to be escaped. NOTE : this is very strange, since it is not documented anywhere. See Official Winscp Mysqldump example . Another thing to note is the exclamation point in the mysql command. This is a shorthand of "call" - a command in winscp that basically allows you to invoke any command you might want to. Last but not least, the command
    ! test \-e temp_dump.sql && echo yes
    
    tests the existence of the output file. You will see "yes" printed if it is there, otherwise blank. This is similar to "dir filename" behavior in DOS.


    Other WinScp automation script

    In this case, I wanted to intercept a buffer in the form of a file. 
    So I needed a script that goes to a directory and copies files. The Winscp script looks like this :
    option echo on
    option confirm off
    open guy:secret@123.123.123.123
    pwd
    cd /tmp
    lcd %TMP%
    get filename1*[0-9]  
    get filename2*[0-9]  
    get filename3*[0-9]  
    exit
    

    this goes to tmp folder locally, and tmp folder remotely, and copies all files with template
    filename1*[0-9], filename2*[0-9], filename3*[0-9].

    this is a very simple yet useful case.

    Saturday, August 21, 2010

    Setting up log4j in a maven project

    I always forget how to quickly set up log4j in my maven project, even though it is really easy.

    I keep getting

    log4j:WARN No appenders could be found for logger (mogi.code.reflection.Utils).
    log4j:WARN Please initialize the log4j system properly.
    

    So if you get this too, and all you want is to get things printed to your console, all you need to do is add a log4j.properties file under src/main/resources folder and populate it with the following text
    log4j.rootLogger=DEBUG, A1
    log4j.appender.A1=org.apache.log4j.ConsoleAppender
    log4j.appender.A1.layout=org.apache.log4j.PatternLayout
    
    # Print the date in ISO 8601 format
    log4j.appender.A1.layout.ConversionPattern=%d [%t] %-5p %c - %m%n
    
    # Print only messages of level WARN or above in the package com.foo.
    log4j.logger.com.foo=WARN
    

    after that you should start seeing your log on console.
    read more about log4j

    Tuesday, August 17, 2010

    When documentation goes wrong - BlazeDS turnkey

    Trying to learn BlazeDS, I am unable to get past the installing documentation stage.
    So here are rules as to "what not to do when documenting". 

    Downloading


    Each page I found that detailed the turnkey download (as containing tomcat etc..) didn't have a link, or had a broken link.

    For example - Google's first result for searching blazeds-turnkey.

    Why do I have to download 40MB tomcat for a lame war? was it too hard to write another packaging ant target??

    Bad naming


    if you have an examples file/folder, don't call it examples.. call it artifactname-examples.

    looking into blazeds content - we have samples.war.. I am NOT going to place this in my tomcat.. I will rename this to blazeds-samples. is it so hard?
    technically it shouldn't bother anyone, unless references to this - meaning, if someone had an image for example referencing to /samples/myimage.gif - then the link will be broken due to rename. However, since this specific case is "samples" - no one should be pointing to it.
    if it was "core.war" I'd probably won't change it even though I want to - since it is likely there are references to core from other wars (see next item on this list).

    Multiple Wars


    Why 3 WARS?
    Am I obligated to have 3 WARS from now on just to use blazeds?
    NO! So why 3 WARS? really..

    Samples, should be as simple as possible. - at least "turnkey" that claims to be a "getting started" session. 3 WARS is not "getting started"..

    Database Connection


    The only "example" tutorial I can think of that needs a DB connection, is a DB component like Hibernate. All other "examples" in the world should be simple enough to use "HashMap".

    BazeDS - Did you write a new ORM model layer? no? than why do I have to "start samples db" before I look at the examples?

    Bad Code


    Last, but not least.. after you finally got the examples running.. you should NEVER get an exception, unless it is demonstrating an example.
    Do whatever you need to avoid it, however, if an exception happens, show it to the user so it will be clear to him the example is not working.

    A request URL will look like this.
    http://my_host/my_context/rest_of_path

    If you are referring to a resource in the same context and host, you should start the reference with a simple "/". however, if you for some reason need to fill in the context and the host, you can always extract that information from the request details. (lots of documentation for this, so I won't elaborate)

    This way - if someone cleverly renamed your WAR, you code will keep on working.

    Unlike the blazeDS samples war that threw his hidden error to firebug console :

    http://localhost:8080/samples/messagebroker/amfpolling   404 no found

    Which clearly happened due to my WAR rename. 

    Conclusion


    When writing a "getting started" examples documentation  :
    • keep it as simple as possible both code-wise and installation-wise. 
    • try to stick to the basics and not do redundant samples like DB connection (unless your module has no meaning without a DB like Hibernate).
    • Write good and clear code - this is a sample(!) so it should be too complex a code to write it safe. 
      • This includes giving meaningful names to files/folder/classes/function etc.. 
    • Make sure the client understand what happens - especially if the example went wrong. Again, this should be a simple code, so this should be so hard to implement. 
    • If possible - make source visible from within the example. 
      • The best thing would be to allow the user to modify the source at run-time, but for some cases, like blazeDS it is impossible. However a good example is www3.schoool's "try-it-yourself" examples. take a look in this border-collapse try it yourself

    Blogger - not for developers?

    As I am writing new posts rapidly, I keep running into an annoying behavior.

    Code syntax may include the character '<' and '>' however these character are also used in HTML.

    When I first started combining HTML and code, I was convinced <pre> tags will solve the problem but they didn't. So the solution is to convert manually all < character to &lt; string. This process is known as "escaping", and for HTML it is called HTML escaping. It exists to all languages since each language has reserved words and characters.



    The most common is the "quotes" which have the backslash as an escape character, in order to enable developers to include the character " inside a string. For example if I want to write :
    The name of the book was "Mogi on Rails"
    I will write the following string
    "The name of the book was \"Mogi on Rails\""
    
    Note that this causes '\' (backslash) character to be a reserved character as well, which requires another escaping. so if I wanted to escape the string above another level I would write
    "\"The name of the book was \\\"Mogi on Rails\\\"\""
    
    And this keeps on and on. This is on my top 10 bug causes in an application.

    Today, I noticed a disturbing behavior in blogger draft.

    take the following code that was written correctly but unescaped:

    List strings;
    

    If the disturbing behavior still occurs you should see an appended string which looks like this
    </string>
    

    however I did not write it. Moreover, blogger modifies the string
    String
    
    to lower case... if you already see it lowered, know I wrote it like this
    String
    


    To make things clearer, or in case the disturbing behavior does not occur any more I added an image that compares the string as I wrote it with how it displayed in draft.




    Why CDATA causes blogger errors?



    Another expected behavior is when you try an obvious solution like adding CDATA tags

    However that causes an even more annoying error
    Your HTML cannot be accepted: Tag is broken: ![CDATA[
    
    Come on!

    Using Compose Mode


    Funny enough the "best" solution is to use the Compose mode, which is a Rich Text Editor mode - that takes care of escaping for you - however, as ironic as it might seem, the audience that needs it the most, usually don't like Rich text editors, so they don't use it.

    We either manually escape character, or we can temporarily switch to "Compose" and paste the code, then go back to "Edit HTML" mode.

    Google Blooper - Translate bar requires FireFox!

    Google just released a new translate bar with a cool feature where you can pause with the mouse on a word, and it will be translated.. you don't need to mark the word or anything like that.
    You can read all about it - just scroll down a bit.

    So naturally, I went to install it using my chrome browser, only to discover it requires Firefox!



    A Blooper?
    I don't know..

    Maybe Google thinks their Chrome Translation bar is enough.. maybe I just need to upgrade my chrome to get this toolbar built in or something.
    In any case this is funny.




    Only Google Can


    In an older post I wrote about My thoughts about Google Translate and the power it holds.

    No one other than Google can dispatch such a toolbar for free as a by the way kind of manner. "By the way.. there's also a toolbar.." .

    So far only chrome automatically offered to translate pages, however Google got this right - it doesn't really matter which browser you use, as long as you get a good translation experience.
    So now.. I guess, we have it in FF as well.


    Blogger Translation Widget


    Weird enough, the context in which I heard about this toolbar was Blogger..



    However, as you've probably seen in the link about, this is not a blogger gadget, but a template modification..
    How weird is that???

    Searching for such a gadget, I couldn't find one.. Weird again!

    How hard can that be?
    Yours truly will try to embark on a mission to write this gadget, following my own blog on writing a blogger gadget from last time.

    Html CSS to Flex Style - about HBox horizontalGap and table border collapse or padding

    The other day I was modifying a file, and I accidentally caused this GUI modification


    The required Look and Feel was the one on the left, where all balls are one beside the other.
    What I did was wrap those circles with an HBox.

    It was obvious to me that I needed a behavior similar to border-collapse for a table or some sort of padding in CSS - as shown in this table style wizard.

    The answer to my question was "horizontalGap". Setting this to 0, gave me the required behavior.

    Sunday, August 15, 2010

    Fail Safe - go.sh script

    Fail Safe - go.sh Script

    As I am deploying my Steps Project Manager application on a Unix host, I came across some failures.
    The application would stop work for some reason - nothing is written to the log.

    Since this is just a hobbie, and not my daily job, and since this application has only 40 users so far,
    hat only 2-3 of them (besides me) actually use it.. I decided on a brute force solution.

    A friend helped me to write a script that runs "forever" and keeps my application up.

    #!/bin/bash 
    
    while true ; do 
    ruby script/server -e production &> res.out  
    done 
    
      

    My session information is saved in a cookie, so I will not lose it.

    Wednesday, August 11, 2010

    Play Framework cannot access public field of anonymous classes

    WOW! do I have a bug for you!
    A while back I started a new job, and the project I am currently working on uses Play Framework! - which is a Rails like implementation in Java.
    Since I already knew Rails, Play came very natural to me. However, I came across an error that only a month and a half later I found the cause to - purely by accident.. I forgot a breakpoint and I was debugging something entirely unrelated, when suddenly it popped right in front of me.

    The Error


    I got the following error

    Oops: IllegalArgumentException
    An unexpected error occured caused by exception IllegalArgumentException: argument type mismatch
    >
    play.exceptions.UnexpectedException: Unexpected Error
            at play.mvc.ActionInvoker.invoke(ActionInvoker.java:300)
            at Invocation.HTTP Request(Play!)
    Caused by: java.lang.IllegalArgumentException: argument type mismatch
            at play.utils.Java.invokeStatic(Java.java:129)
            at play.mvc.ActionInvoker.invoke(ActionInvoker.java:163)
            ... 1 more
    
    

    It doesn't get any more general that that. If you don't see anything on the browser, always look in the console.

    What naturally occurred to me was "argument type mismatch ==> I have a problem with url mapping to a function signature". Well, not at all.. At some point I found a pattern, which can only mean that a certain flow can cause this. Once I accidentally found that flow, problem was quickly solved.

    The Solution


    It turns out that if you wrap the correct code correctly with try/catch you can finally see the causing exception, which says this :
    java.lang.IllegalAccessException: Class play.classloading.enhancers.PropertiesEnhancer$FieldAccessor can not access a member of class com.name.XXX$1 with modifiers "public"
    

    the com.name.XXX is a fake class name.
    The important part of the message is $1 and "can not access a member with modifier public"..

    Every 6 years young kid knows that you can access a public field. So what is the problem?

    Reproducing


    The problem is with a code that looks like this in play

    ....
    
    MyDoer doer  = new MyDoer;
    
    public static void myFunc(){
    
          doer.doSomething(new IResultListener(){
                       public String result;
                       @Override 
                       public void handleResult(String str){
                              result = str;
                        }
    
                 }
    
    }
    
    ...
    
    

    Where doer can do whatever it likes...
    The "public String result" is not accessible for some really odd reason.
    This is of course a bug in Play Framework.

    Code Modifications


    In order to get rid of this error, all you should do is make that anonymous class a "named class" or not-anonymous class.



    Afterthought


    As I am writing this post, I wrote the sample code above.. it seems that if you handle your exceptions correctly, you will see the error as it happens.

    Here is the picture of the error that I saw in reproduction :



    This lead me to think.. hmmm.. we have another bug!!!


    Obviously, if the simplest reproduction gives me an exception and my application gets another exception, there's another problem with my application.

    Remember, the original exception was :

    Caused by: java.lang.IllegalArgumentException: argument type mismatch
    

    Since I solved the previous bug, I had to reproduce this one in another way.
    Thank god for my persistence with reproducing, because the problem popped right away.

    At first I tried to write
    throw new RuntimeException("myException");
    

    however this did not reproduce the problem.
    Now remember the exception I found today said
    java.lang.IllegalAccessException

    So I tried writing
    throw new IllegalAccessException("myException");
    

    because this HAD to reproduce the problem.. no other option is available.
    BUT THEN! the IDE told me I have a compilation error (good sign) because IllegalAccessException is not a RuntimeException!!!!!!

    And this is the answer I was looking for.
    Someone wrote a function expecting a RuntimeException but instead got an Exception (or to be more specific IllegalAccessException) which does not extend RuntimeException.

    Since I know play and the source so far, I had a lucky guess.
    You can write a @Catch function - that catches all the errors in the application.

    I found the following signature
     @Catch(value={Exception.class})
        protected static void incapCatch( RuntimeException e )
    

    Which is EXACTLY what I was looking for!!!
    All I had to do is modify this code to
     @Catch(value={Exception.class})
        protected static void myCatch(Exception e )
    

    and problem was solved.

    Critical Bugs


    The bug I found was critical for 2 reasons :
  • It belonged to an error reporting flow

    The problem in these scenarios is that you never really know where the problem really is. An error printing mechanism must never have a bug otherwise it will be hard to resolve.


  • This is a general framework reflection error
    a reflection error is really hard to solve when it's not your code , and doesn't contain the information. Impossible to pin point. This is clearly Play!Frameworks problem, and I will let them know about it


  • This is a fundamental bug
    This happens to the best of the best at some point. Once you see Exception.class in an annotation written next to a RuntimeException signature, you can identify this bug. Hack, this can even be a question in your Java beginners course. However.. mistakes happen. But the more fundamental, the wider its scope, and the more effect it will have on your application.


  • Importance of Reproducing


    I could not have discovered all these bugs and solutions if I did not insist on reproducing them first. Reproducing a bug tells you :
  • You understand the problem

  • You understand the solution

  • You know what to expect when something goes wrong

  • You know what to expect when something goes right


  • And it can't get any better than that.

    Friday, August 6, 2010

    My First Blogger Gadget (Widget) - The Reference Gadget




    I follow blogger closely, and I enjoy everything I see.
    However, from time to time I feel something is missing.

    It's time I began being more active.



    This post is not about Blogger Hacks


    What is a blogger "hack"


    A hack in blogger is a piece of code you can place in the "template" of the blog, and that will generate the source you want. For example - you can write JavaScript in the template to generate "Table Of Contents" div.
    This method is used when you need to modify the content of the post - since the "document" referred to in JavaScript is the same "document" of the post, it is usually an easier and quicker way than a gadget to achieve your goal.

    I don't think the word "hack" but that's the most commonly used phrase in this case.

    This post is about Gadgets


    A gadget will add information to your post, but will not modify it.
    You can still add Table of Contents but it will not look and feel as part of the post.

    A gadget uses the blogger API to achieve its goal and is not considered a hack in any way.
    However it is considered harder than a hack since it requires you to learn the Blogger's API and use it in JavaScript. You cannot use the commands you know in JavaScript since the gadget's "document" and the post's document is different.

    This is however not the case if the data the gadgets is showing is unrelated to the post. (Advertisement for example).

    The Reference Gadget


    I try to maintain a "references" section in each post I have links in. (Like this one).
    However.. I believe this should be automated, and it annoyed me there's no such gadget.

    Writing Your First Blogger Gadgets


    The first thing you will notice trying to write your first gadget is that there's a lot of documentation, but its quality is so low.. it's disturbing.
    It's organized and everything, but the information you need is missing.

    That's probably because you reached Blogger Developer Network or Google Gadget Developer Guide which both seem great, but they are the wrong documentations for this case.


    Surprisingly enough, these are the first result you get when searching "blogger widget api".
    What you should be looking for is "blogger gadget api". - the difference is between widget and gadget.
    Quoting an article about the difference between gadgets and widgets :

    The easiest way to explain it is that a gadget is any widget that is not a widget. Sound confusing? A widget is a piece of reusable code that you can plug into virtually any website. A gadget acts just like a widget, often fulfilling the same purpose, but it is proprietary. It only works on a certain website or a specific set of websites.

    Getting Started


    You start with the following template

    <?xml version="1.0" encoding="UTF-8"?>
    <Module>
    <ModulePrefs title="References"
                   author="Guy Mograbi"
                   author_email="guy.mograbi@gmail.com"
                   description="Takes links and shows them as list"
                  title_url="http://www.mograbi.co.il" >
      </ModulePrefs>
      <Content type="html">
        <![CDATA[
      Hello world!
        ]]>
      </Content>
    </Module>
    

    Just modify author, author_email and so on. (you can also add "screenshot" and "thumbnail" - but I am guessing you'll be doing that once you have an image of your gadget :) )

    Running the gadget


    Need to make the XML accessible somehow


    Don't wait for this step, once you have the XML above accessible somewhere online you should load it to your blog (or some fake temporary blog you have).
    I tried following the test tutorial in documentation, but it failed for me. I found it quicker to test it on an actual blog.

    You can host your file on Google Code or Github.
    For example - mine is available on Google Code
    Don't try the Google Gadget Editor since it is full of bugs. (and I am using chrome, so its not a compatibility issue).


    Best practice says to use some online files repository, where you can write an XML file and save it online - however there's no such thing (STARTUP!)
    Update: Actually, now you can finally edit files online in Github and Google Code

    Add the gadget to a blog


    Pick a blog you don't care to make inaccessible for some time (expect javascript errors).
    Click "design" ==> "add gadget" ==> "add your own".
    Give the URL to the XML which should now be accessible online.

    View your blog - you should see "hello world!".
    Everything went smoothly for me to this point. (after a lot of research I summarized above) - so there's no troubleshooting, only "best practice" advice.

    Writing Gadget Functionality


    Now that you have the gadget up and running, with a good work process, it's finally time to start coding.

    Disabling Gadget's Cache

    Try to modify your XML in any way - for example, modify the "Hello World" string and hit refresh in your blog. Did it change?
    I expect the answer to be NO and the reason for that is that blogger caches the Gadget's XML.

    In order to disable the cache, you will need to modify the template of the blog (hack).

    Add the following lines before </head>
    <script src='http://www.google.com/friendconnect/script/friendconnect.js' type='text/javascript'></script>
    <script type="text/javascript">google.friendconnect.container.setNoCache(1);</script>
    

    This code was taken from Blogger's Documentation about testing

    Getting info From Blogger


    As I mentioned before - if all you want is to show data unrelated to the post, simply write your HTML and JavaScript, there's nothing new for you to learn here.
    However, since I want to gather all the links in the post and display them as a list of links, I will need the content of the post.

    This requires me to get the content of the post by using Blogger's API.
    Reading in Blogger's data api documentation I decided to write code that looks like this

    <div id="hidden_div" style="display:none"></div>
     <div id="references_mogi_gadget"></div>
    
      <script>
    
     function $(id){ return document.getElementById(id);}
     
     function write_references(){ 
      var ref_div = $('references_mogi_gadget');
      if (ref_div == null){
       ref_div = document.createElement('div');
       document.body.appendChild(ref_div);
      }
      
      as = document.getElementsByTagName('a');
      for each (a in as){
       
       if ( a.className && a.className.indexOf('mogi-reference') >=0) {
       
        var li = document.createElement('li');
        
        var newa = document.createElement('a');
        // I don't know why but JSON strips the http: part..
        
        newa.href=a.href;
        newa.target = 'top';
        newa.innerHTML = a.innerHTML;
        li.appendChild(newa);
        ref_div.appendChild(li);
       
       }
      } 
     }
     
      function onLoadFeed(data){
      var content = data.data.entry.content.$t;
      
      $('hidden_div').innerHTML = content;
      write_references();
       }
       
     // Get the feed data
           blog = new google.Blog(function() {
             blog.getCurrentPostJson(onLoadFeed);
           }, window.name);
     
    
    </script>
    
        
    


    Lets break it down


    The first thing to run is "fetch post content" code
    // Get the feed data
           blog = new google.Blog(function() {
             blog.getCurrentPostJson(onLoadFeed);
           }, window.name);
    

    I give the constructor a function - which is invoked by the end of the constructor. (as seen in documentation).

    Then, we get to "onLoadFeed"
    function onLoadFeed(data){
      var content = data.data.entry.content.$t;
      
      $('hidden_div').innerHTML = content;
      write_references();
       }
    

    What I basically do is pour the content of the reply to a hidden div. The reason I do that is because I want to handle JavaScript code, and not start parsing HTML code..

    Then I run an algorithm that finds all links with class="mogi-reference" and put them nicely in a list. this is the "write_references" function which is pure JavaScript - no blogger api specifics..

    This is my first draft.. but running it, I get the result I wanted.
    All I have left is to match the style of the gadget to the style of the blog and add customizations etc..

    Future Features


    More features I can add easily are :
  • add a small description of the link by adding attribute to anchor tag


  • add "group" attribute to anchor tags, and group the links to different lists



  • This will give all my viewers an easy "references" box which I won't have to make manually anymore.

    The Gadget gets Cached Data!!!!


    As I was testing my gadget, I accidentally had a problem with the blog's content. So I modified it, but it didn't change in the gadget!!! denying me to test with proper data.

    This is how I learned that gadgets get cached data. This might be a problem.
    I found posts that claim to solve the problem. nothing worked.
    Eventually, after a couple of minutes, the cache refreshed, and I continued, but you should be aware of this. If you insist on not waiting - simply create a new post.

    Here is an image showing that the gadget is out of sync with the post.
    According to my code, I am taking the entire anchor tag, with its inner HTML, so the text for the link should be the same, but it's not.


    The text in the gadget saying "My Site" should match the link in the post saying "Google"
    but it's not since it is using a cached version of the post. 

    Applying the Style


    The style part is quite easy, all you have to do is get the style from blogger api, and apply it in the correct places.
    Just read the documentations

    <ModulePrefs ... >
              ... 
     
     
              ....
         </ModulePrefs>
    
    <body id='myBody'>
    ... 
    <script>
     $('myBody').style.borderColor = gadgets.skins.getProperty('BORDER_COLOR');
     $('myBody').style.backgroundColor = gadgets.skins.getProperty('CONTENT_BG_COLOR');
     $('myBody').style.color = gadgets.skins.getProperty('CONTENT_TEXT_COLOR');
     $('myBody').style.font = gadgets.skins.getProperty('FONT_FACE');
    /// use $('linkId').style.color = gadgets.skins.getProperty('CONTENT_LINK_COLOR');
    // on every "a" tag. 
    </script>
    
         .... 
        
    

    This should pretty much cover everything..

    Best Practice I Learned


    I learned that firebug or writing "debugger" in the JavaScript code is not useful. I couldn't find a proper way to debug the code.
    So I had to resort to alerts.. thank god this gadget was pretty easy.

    Where to get my Gadget?

    All the info you need is at google code project

    Tuesday, August 3, 2010

    Generics - method signature type definition

    On my previous post I introduce some advanced things about generics, when I discovered I forgot a very important feature.

    As specified before, you can declare a generic type on a method declaration.


    public <T> T newInstance(Class<T> clzz, String name) throws IllegalAccessException, InstantiationException
        {
           return (T) Spring.getBean( "myBean" );
        }
    

    disregarding for a moment the ugly cast. (in this case you better use Class#cast function).
    as you can see, I don't really need "clzz" there. I use it only to define T.
    However you can also do without it"Class<T> clzz".

    You can also write the following function definition
    public <T> T newInstance(String name) throws IllegalAccessException, InstantiationException
        {
           return (T) Spring.getBean( "myBean" );
        }
    


    and call it like this
    public void test() throws InstantiationException, IllegalAccessException
        {
            String str = this.<String>newInstance( "guy" );
        }
    

    In this specific case, you don't really need to specify <T> since it is "inferred" and so the compiler will tell you
    Explicit type arguments can be inferred
    

    however when you get to inheritance and scenarios which are more complex than this one, it will no longer be inferred.

    NOTE : This was tested on JDK 1.6. I am unsure about 1.5 compatibility.

    Compiler Support Issue


    Some of you might try this and get the following message :
    type parameters of   T cannot be determined; no unique maximal instance exists for type variable T with upper bounds, java.lang.Object
    

    Intellij users will run into this the fastest..

    It seems this is compiler dependend.

    Java has several compilers :



  • Javac










  • Jikes










  • Eclipse








  • probably more, but these are the compilers intellij supports.
    Each with its own advantages.

    However - it seems that when working on Intellij, you get JavaC as default compiler, but that compiler cannot handle the syntax shown above!! - you can reproduce the problem from command line.

    To resolve this, all you need to do is tell intellij to use Eclipse Compiler.
    Settings ==> Compiler ==> Java Compiler ==> Use compiler : Eclipse




    And the error will go away.
    HOWEVER - NOTE - Once you use the eclipse compiler, you should insert the target/source attributes to command line :
    like this :
    -target 1.6 -source 1.6
    

    or whatever version you use.

    There's also a comment in a "YouTrack" thread by intellij that explains this while suggesting a different solution.


    Configuring Eclipse Compiler in a Maven Project


    If you are compiling with Maven, you should define the eclipse compiler as such
    <plugin>
        <artifactId>maven-compiler-plugin</artifactId>
        <configuration>
            <compilerId>eclipse </compilerId>
            <source>1.6</source>
            <target>1.6</target>

        </configuration>
        <dependencies>
            <dependency>
                <groupId>org.codehaus.plexus</groupId>
                <artifactId>plexus-compiler-eclipse</artifactId>
                <version>1.8</version>
            </dependency>
        </dependencies>
    </plugin>

    You can also read about configuring other compiler