<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/css" href="/stylesheets/rss.css"?>
<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/">
  <channel>
    <title>Object Mentor Blog: Writing Java Aspects ... with JRuby and Aquarium!</title>
    <link>http://blog.objectmentor.com/articles/2008/02/25/writing-java-aspects-with-jruby-and-aquarium</link>
    <language>en-us</language>
    <ttl>40</ttl>
    <description></description>
    <item>
      <title>Writing Java Aspects ... with JRuby and Aquarium!</title>
      <description>&lt;p&gt;&lt;a href="http://aquarium.rubyforge.org"&gt;Aquarium&lt;/a&gt; V0.4.0, my &lt;span class="caps"&gt;AOP&lt;/span&gt; library for Ruby, now supports &lt;a href="http://jruby.codehaus.org/"&gt;JRuby&lt;/a&gt;. Not only do the regular &amp;#8220;pure Ruby&amp;#8221; Aquarium specs run reliably under JRuby (V1.1RC2), but you can now write aspects for Java types with Aquarium!&lt;/p&gt;


	&lt;p&gt;There are some &lt;strong&gt;important&lt;/strong&gt; limitations, though. Cartographers of old would mark dangerous or unknown territory on their maps with &lt;a href="http://en.wikipedia.org/wiki/Here_be_dragons"&gt;&lt;em&gt;hic sunt dracones&lt;/em&gt;&lt;/a&gt; (&amp;#8220;here be dragons&amp;#8221;), a reference to the old practice of adorning maps with serpents around the edges.&lt;/p&gt;


	&lt;p&gt;This is true of Aqurium + Java types in JRuby, too, at least for now.&lt;/p&gt;


	&lt;p&gt;Aquarium uses Ruby&amp;#8217;s metaprogramming &lt;span class="caps"&gt;API&lt;/span&gt; extensively and the JRuby team has done some pretty sophisticated work to integrate Java types with Ruby. Hence, it&amp;#8217;s not too surprising there are some &lt;em&gt;gotchas&lt;/em&gt;. Hopefully, workarounds will be possible for all of them.&lt;/p&gt;


	&lt;p&gt;The details are discussed on the &lt;a href="http://aquarium.rubyforge.org/jruby.htm"&gt;JRuby page&lt;/a&gt;, the &lt;a href="http://aquarium.rubyforge.org/rdoc/files/README.html"&gt;&lt;span class="caps"&gt;README&lt;/span&gt;&lt;/a&gt; on the Aquarium site, and of course the &amp;#8220;specs&amp;#8221; in the distribution&amp;#8217;s &lt;code&gt;jruby/spec&lt;/code&gt; directory. I&amp;#8217;ll summarize them here, after discussing the pros and cons of Aquarium &lt;em&gt;vs.&lt;/em&gt; the venerable &lt;a href="http://www.aspectj.org"&gt;AspectJ&lt;/a&gt; and showing you an example of using Aquarium for Java.&lt;/p&gt;


	&lt;p&gt;Briefly, Aquarium&amp;#8217;s advantages over AspectJ are these:&lt;/p&gt;


	&lt;ol&gt;
	&lt;li&gt;You can add &lt;strong&gt;and&lt;/strong&gt; remove advice dynamically at runtime. You can&amp;#8217;t remove AspectJ advice.&lt;/li&gt;
		&lt;li&gt;You can advise &lt;span class="caps"&gt;JDK&lt;/span&gt; types easily with Aquarium. AspectJ won&amp;#8217;t do this by default, but this is really more of a legacy licensing issue than a real technical limitation.&lt;/li&gt;
		&lt;li&gt;You can advise individual &lt;em&gt;objects&lt;/em&gt;, not just types.&lt;/li&gt;
	&lt;/ol&gt;


	&lt;p&gt;Aquarium&amp;#8217;s disadvantages compared to AspectJ include:&lt;/p&gt;


	&lt;ol&gt;
	&lt;li&gt;Aquarium will be slower than using AspectJ (although this has not been studied in depth yet).&lt;/li&gt;
		&lt;li&gt;Aquarium&amp;#8217;s pointcut language is not as full-featured as AspectJ&amp;#8217;s.&lt;/li&gt;
		&lt;li&gt;There are the bugs and limitations I mentioned above in this initial V0.4.0 release, which I&amp;#8217;ll elaborate shortly.&lt;/li&gt;
	&lt;/ol&gt;


	&lt;p&gt;Here is an example of adding tracing calls to a method &lt;code&gt;doIt&lt;/code&gt; in all classes that implement the Java interface &lt;code&gt;com.foo.Work&lt;/code&gt;.&lt;/p&gt;


&lt;pre&gt;&lt;code&gt;
Aspect.new :before, :calls_to =&amp;gt; [:doIt, :do_it], :in_types_and_descendents =&amp;gt; Java::com.foo.Work do |jp, obj, *args|
  log "Entering: #{jp.target_type.name}##{jp.method_name}: object = #{object}, args = #{args.inspect}" 
end
&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;There are two important points to notice in this example:&lt;/p&gt;


	&lt;ol&gt;
	&lt;li&gt;You can choose to refer to the method as &lt;code&gt;do_it&lt;/code&gt; (Ruby style) or &lt;code&gt;doIt&lt;/code&gt;, but these variants are effectively treated as &lt;strong&gt;separate&lt;/strong&gt; methods; advice on one will not affect invocations of the other. So, if you want to be sure to catch &lt;strong&gt;all&lt;/strong&gt; invocations, use &lt;strong&gt;both&lt;/strong&gt; forms. There is a bug (18326) that happens in certain conditions if you use just the Java naming convention.&lt;/li&gt;
		&lt;li&gt;If the type is an interface, you must use &lt;code&gt;:types_and_descendents&lt;/code&gt; (or one of the supported variants on the word &lt;code&gt;types&lt;/code&gt;...). Since interfaces don&amp;#8217;t have method implementations, you will match no join points unless you use the &lt;code&gt;_and_descendents&lt;/code&gt; clause. (By default, Aquarium warns you when no join points are matched by an aspect.) However, there is a bug (18325) with this approach if Java types are subtyped in Ruby.&lt;/li&gt;
	&lt;/ol&gt;


	&lt;h4&gt;Limitations and Bugs&lt;/h4&gt;


	&lt;p&gt;Okay, here&amp;#8217;s the &amp;#8220;fine print&amp;#8221;...&lt;/p&gt;


	&lt;p&gt;In this (V0.4.0) release, there are some important limitations.&lt;/p&gt;


	&lt;ol&gt;
	&lt;li&gt;Aquarium advice on a method in a Java type will &lt;strong&gt;only&lt;/strong&gt; be invoked when the method is called &lt;strong&gt;directly&lt;/strong&gt; from Ruby.&lt;/li&gt;
		&lt;li&gt;To have the advice invoked when the method is called from &lt;strong&gt;either&lt;/strong&gt; Java &lt;strong&gt;or&lt;/strong&gt; Ruby, it is necessary to create a Ruby subclass of the Java type and override the method(s) you want to advise. These overrides can just call &lt;code&gt;super&lt;/code&gt;. Note that it will also be necessary for &lt;strong&gt;instances&lt;/strong&gt; of this Ruby type to be used throughout the application, in both the Java and Ruby code. So, you&amp;#8217;ll have to instantiate the object in your Ruby code.&lt;/li&gt;
	&lt;/ol&gt;


	&lt;p&gt;Yea, this isn&amp;#8217;t so great, but if you&amp;#8217;re motivated&amp;#8230; ;)&lt;/p&gt;


	&lt;p&gt;There are also a few outstanding Aquarium bugs (which could actually be JRuby bugs or quirks of the Aquarium-JRuby &amp;#8220;interaction&amp;#8221;; I&amp;#8217;m not yet sure which).&lt;/p&gt;


	&lt;ol&gt;
	&lt;li&gt;&lt;strong&gt;Bug #18325&lt;/strong&gt;: If you have Ruby subclasses of Java types &lt;strong&gt;and&lt;/strong&gt; you advise a Java method in the hierarchy using &lt;code&gt;:types_and_descendents =&amp;gt; MyJavaBaseClassOrInterface&lt;/code&gt; &lt;strong&gt;and&lt;/strong&gt; you call unadvise on the aspect, the advice &amp;#8220;infrastructure&amp;#8221; is not correctly removed from the Ruby types. Workaround: Either don&amp;#8217;t &amp;#8220;unadvise&amp;#8221; such Ruby types or only advise methods in such Ruby types where the method is explicitly overridden in the Ruby class. (The spec and the &lt;a href="http://rubyforge.org/tracker/index.php?func=detail&amp;#38;aid=18325&amp;#38;group_id=4281&amp;#38;atid=16494"&gt;Rubyforge bug report&lt;/a&gt; provide examples.)&lt;/li&gt;
		&lt;li&gt;&lt;strong&gt;Bug #18326&lt;/strong&gt;: Normally, you can use either Java- or Ruby-style method names (&lt;em&gt;e.g.,&lt;/em&gt; &lt;code&gt;doSomething&lt;/code&gt; vs. &lt;code&gt;do_something&lt;/code&gt;), for Java types. However, if you write an aspect using the Java-style for a method name and a Ruby subclass of the Java type where the method is actually defined (i.e., the Ruby class doesn&amp;#8217;t override the method), Aquarium acts like the JoinPoint is advised, but the advice is never actually called. Workaround: Use the Ruby-style name in this scenario.&lt;/li&gt;
	&lt;/ol&gt;


	&lt;p&gt;So, there is still some work to do, but it&amp;#8217;s promising that you can use an aspect framework in one language with another. A primary goal of Aquarium is to make it easy to write simple aspects. My hope is that people who might find AspectJ daunting will still give Aquarium a try.&lt;/p&gt;</description>
      <pubDate>Mon, 25 Feb 2008 22:10:00 +0000</pubDate>
      <guid isPermaLink="false">urn:uuid:4645fddb-ba4f-4e8d-8283-7732439d017f</guid>
      <author>Dean Wampler</author>
      <link>http://blog.objectmentor.com/articles/2008/02/25/writing-java-aspects-with-jruby-and-aquarium</link>
      <category>JRuby</category>
      <category>aquarium</category>
      <category>Java</category>
      <category>aspects</category>
      <category>AOP</category>
      <category>AOSD</category>
    </item>
    <item>
      <title>"Writing Java Aspects ... with JRuby and Aquarium!" by James Carr</title>
      <description>&lt;p&gt;Guess what&amp;#8217;s going on my laptop once I get it back with a new hard drive? It&amp;#8217;ll really be interesting to see what craziness I&amp;#8217;ll cook up with this. ;)&lt;/p&gt;


	&lt;p&gt;Useful!&lt;/p&gt;</description>
      <pubDate>Wed, 27 Feb 2008 01:42:42 +0000</pubDate>
      <guid isPermaLink="false">urn:uuid:86d2c96e-fee2-4f0d-8c50-100430ffd2d3</guid>
      <link>http://blog.objectmentor.com/articles/2008/02/25/writing-java-aspects-with-jruby-and-aquarium#comment-1620</link>
    </item>
    <item>
      <title>"Writing Java Aspects ... with JRuby and Aquarium!" by AJit</title>
      <description>&lt;p&gt;You sold aquarium to me. I am quite convinced of its benefits. Hehe. I should try it sometime soon.&lt;/p&gt;</description>
      <pubDate>Tue, 26 Feb 2008 06:57:57 +0000</pubDate>
      <guid isPermaLink="false">urn:uuid:c8eda8ae-b56a-4140-8455-9cb7906e8b6c</guid>
      <link>http://blog.objectmentor.com/articles/2008/02/25/writing-java-aspects-with-jruby-and-aquarium#comment-1619</link>
    </item>
  </channel>
</rss>
