Friday, March 11, 2011

Scala with SBT and Eclipsify

So, I'm new to Scala but wanted to start playing with it. The language, concepts and future of this language are very exciting. One thing I am noticing is that the plugins are very imature. Please note here that I am not criticising anyone working on the plugins. I am simply noting that they haven't been around for a thousand years and put through their paces like their Java counterparts.

I've recently fought to get a simple project created using sbt and imported in to eclipse using sbt eclipsify. Unfortunately, being so new to these tools, I struggled a bit. Below is a summary of how I achieved it.

  1. Download SBT and get it running... this is pretty simple and the directions located here explain it very well.  
  2. Now that you have SBT downloaded and setup, it is runnable from the command line in any directory.  Navigate to where your eclipse projects are normally kept, in my case
  3. D:\>cd D:\development\workspace
    D:\development\workspace>mkdir Concepts
    D:\development\workspace>cd Concepts
    D:\development\workspace\Concepts>sbt
    D:\development\workspace\Concepts>set SCRIPT_DIR=D:\cory\sbt\
    D:\development\workspace\Concepts>java -Xmx512M -jar "D:\cory\sbt\sbt-launch-0.7.4.jar"
    Project does not exist, create new project? (y/N/s) y
    Name: Concepts
    Organization: Maksymchuk
    Version [1.0]:
    Scala version [2.7.7]:
    sbt version [0.7.4]:
    Getting Scala 2.7.7 ...
    :: retrieving :: org.scala-tools.sbt#boot-scala
    confs: [default]
    2 artifacts copied, 0 already retrieved (9911kB/593ms)
    Getting org.scala-tools.sbt sbt_2.7.7 0.7.4 ...
    :: retrieving :: org.scala-tools.sbt#boot-app
    confs: [default]
    15 artifacts copied, 0 already retrieved (4096kB/719ms)
    [success] Successfully initialized directory structure.
    [info] Building project Concepts 1.0 against Scala 2.7.7
    [info] using sbt.DefaultProject with sbt 0.7.4 and Scala 2.7.7
    >
    
  4. So now you have it, a project created using SBT sitting on your file system. Well done. Now the tricky part, using Eclipsify to get it into Eclipse.
  5. I downloaded Eclipsify from here, then extracted the zip on to my filesystem.  In the unzipped file system, I navigated to "musk-SbtEclipsify-ca279bd/dist" and coppied the file "sbteclipsify-0.4.0.jar" from there to a new folder I created in "Concepts\project\plugins" where concepts is the directory created above.
  6. Now create a Scala file in the concepts directory called "Plugins.scala" as follows
  7. import sbt._ 
    class Plugins(info: ProjectInfo) extends PluginDefinition(info) {   
     val a = "de.element34" % "sbt-eclipsify" % "0.7.0"  
    }
    
  8. Next, create a file called Concepts.scala in Concepts\project\build
  9. import sbt._
    import de.element34.sbteclipsify._
    class Concepts(info: ProjectInfo) extends DefaultProject(info) with Eclipsify {
      // the project definition here
    }
    
  10. Now in your command line window (running sbt) run this command
  11. > reload
    
  12. This should have created an eclipse command that can be used in the SBT console
  13. > eclipse
    
  14. Now go to Eclipse and import your project! The files you need have been generated.

Thursday, November 26, 2009

JAX-WS Fighting with com.sun.xml.ws.server.UnsupportedMediaException

So I was running a JAX-WS stub from my application and kept getting this exception:


Exception: ------
com.sun.xml.ws.server.UnsupportedMediaException: Unsupported Content-Type: text/html; charset=ISO-8859-1 Supported ones are: [text/xml]
at com.sun.xml.ws.encoding.StreamSOAPCodec.decode(StreamSOAPCodec.java:295)
...


Its pretty obvious to see that the webservice is expecting XML/SOAP back as a response but instead is getting HTML. It could be the firewall, our authenitication layer, a DNS error, a reverse proxy error, an application server error page... anything really.


What a terrible exception. Worse yet, as I am using the JAX-WS framework, there was no real way to find out what the html was in the response, or so I though. I spent more than a few hours trying to find out how. Finally, I found this little nugget... When starting up your application server java process, pass this in as a VM argument:


-Dcom.sun.xml.ws.transport.http.client.HttpTransportPipe.dump="true"

Now the response is spit out to stdout! Hope this helps anyone fighting the same problems.

Cheers,

Yeuker

Wednesday, November 25, 2009

Getting the proxied object from a dynamic spring proxy

In a project I am currently working on, we are using Spring-AOP. Spring's AOP implementation 'transparently' proxies objects to facilitate its AOP implementation. You have the choice of CGLIB proxies (class based proxying) or JDK Dynamic Proxies (interface base proxying). Either one is fine... but there came a time when my proxied object didn't quite behave like the object it was proxying. I was trying to get a hibernate DataSource object from a SessionFactory using this code:

DataSource ds = SessionFactoryUtils.getDataSource(sf);

Unforunately, because my SessionFactory is a proxy object, this code was returning null... still not sure why. I knew it worked with the 'un-proxied' SessionFactory, so needed to get access to it. If you are ever in this bind, here is a snippit that will work:

public T getTargetObject(Object proxy, Class targetClass) throws Exception {
if (AopUtils.isJdkDynamicProxy(proxy) && proxy instanceof Advised) {
return (T) ((Advised)proxy).getTargetSource().getTarget();
} else {
return (T) proxy;
}
}

Hope this helps! Any comments, please post'em.

Cheers,

Yeuker

Tuesday, October 13, 2009

Synchronously loading external javascript files

I ran in to an interesting problem recently. I needed to modify a web page but had no access to the page itself, just the javascript files that were used on the page. My solution was to use jQuery and modify the elements through javascript.

My first problem was that I needed to load jQuery javascript file, not via inline html with the

<script ... ></script>


tag, but inside from inside another javascript file. There are plenty of websites explaining how to do this with code like:

function loadjsfile(filename){
var fileref;
fileref=document.createElement('script')
fileref.setAttribute("type","text/javascript")
fileref.setAttribute("src", filename)
var html_doc = document.getElementsByTagName('head')[0];
html_doc.appendChild(fileref);
}

loadjsfile('jquery.js');
loadjsfile('file1.js');
loadjsfile('file2.js');



The problem here is that these files will not load synchronously. I.e. I need file 1 to load after jQuery and file 2 to load after file 1 but using the above method, the files will load asynchronously... which will cause everything to fail. Then I stumbled on this blog post:

http://www.phpied.com/javascript-include-ready-onload/

Which showed me the trick of attaching the onreadystatechange and onload events to the file... nice work guys.

Next, I took their script and modified it a little bit to:
  1. Use an array and a little bit of recursion to load synchronously instead of simply popping up alerts
  2. Load both css and js files in one method
  3. Added fileref.readyState == 'loaded' to the ie code for IE7


// create a 2 dimentional array  - 3 files
var myArray=new Array(3)
for (i=0; i < myArray.length; i++) { 
myArray[i]=new Array(2) 

}

myArray[0][0]="somecssfile.css";
myArray[0][1]="css";

myArray[1][0]="jquery.js";
myArray[1][1]="js";

myArray[2][0]="dependsonjquery.js";
myArray[2][1]="js";

var fileref;
var index = 0;

function loadjscssfile( ) {

//if filename is a external JavaScript file    
//alert('loading = ' + myArray[index][0])
if (myArray[index][1]=="js"){   
fileref=document.createElement('script')
fileref.setAttribute("type","text/javascript")
fileref.setAttribute("src", myArray[index][0])
}

//if filename is an external CSS file
else if (myArray[index][1]=="css"){ 
fileref=document.createElement("link")
fileref.setAttribute("rel", "stylesheet")
fileref.setAttribute("type", "text/css")
fileref.setAttribute("href", myArray[index][0])
}

if (typeof fileref!="undefined") {  
var html_doc = document.getElementsByTagName('head')[0];
html_doc.appendChild(fileref);
}




// IE
fileref.onreadystatechange = function () {    
// complete is for ie6,                 loaded is for ie7
if (fileref.readyState == 'complete' || fileref.readyState == 'loaded') {                  
var fileName;                        
fileref.getAttribute('src') == null ? fileName = fileref.getAttribute('href') : fileName = fileref.getAttribute('src') ;  
//alert('loaded = ' + fileName)
index++;                  
if (index <  myArray.length) {  
loadjscssfile();
}

}
}

// Firefox
fileref.onload = function () {    
if (!(/MSIE (\d+\.\d+);/.test(navigator.userAgent))) { //test for MSIE x.x;
index++;                  
if (index <  myArray.length) {  
loadjscssfile();
}
}        
}
return false;
}

loadjscssfile(); 



Works like a charm... now you know :-). Any questions, please post'em.