<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Here comes the Sun &#187; groovy</title>
	<atom:link href="http://sunng.info/blog/tag/groovy/feed/" rel="self" type="application/rss+xml" />
	<link>http://sunng.info/blog</link>
	<description>47% users on this site use *nix</description>
	<lastBuildDate>Sat, 04 Feb 2012 13:08:19 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.1</generator>
		<item>
		<title>GPars的Actor实现</title>
		<link>http://sunng.info/blog/2011/04/gpars%e7%9a%84actor%e5%ae%9e%e7%8e%b0/</link>
		<comments>http://sunng.info/blog/2011/04/gpars%e7%9a%84actor%e5%ae%9e%e7%8e%b0/#comments</comments>
		<pubDate>Thu, 28 Apr 2011 15:32:22 +0000</pubDate>
		<dc:creator>sunng</dc:creator>
				<category><![CDATA[手艺]]></category>
		<category><![CDATA[groovy]]></category>
		<category><![CDATA[java]]></category>
		<category><![CDATA[opensource]]></category>

		<guid isPermaLink="false">http://sunng.info/blog/?p=853</guid>
		<description><![CDATA[Actor是一种Continuation技术，可以在少量的线程运行大量Actor对象。Actor对象之间通过消息机制进行交互。而Actor本身线程安全，这样的模型使并发编程的复杂度降低，同时也在一定的场景下实现了可扩展性。 gpars是Java和Groovy都可以使用的并行编程库，他实现了Actor、Agent、DataFlow等模型，旨在为Groovy提供高层的并行编程模型。以下分析gpars 0.12中非阻塞Actor的实现。 @Grab&#40;&#34;org.codehaus.gpars:gpars:0.11&#34;&#41; import groovyx.gpars.actor.Actors def worker = Actors.actor &#123; &#160; &#160; loop &#123; &#160; &#160; &#160; &#160; react &#123; &#160; &#160; &#160; &#160; &#160; &#160; reply it.reverse&#40;&#41; &#160; &#160; &#160; &#160; &#125; &#160; &#160; &#125; &#125; def console &#8230; <a href="http://sunng.info/blog/2011/04/gpars%e7%9a%84actor%e5%ae%9e%e7%8e%b0/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>Actor是一种Continuation技术，可以在少量的线程运行大量Actor对象。Actor对象之间通过消息机制进行交互。而Actor本身线程安全，这样的模型使并发编程的复杂度降低，同时也在一定的场景下实现了可扩展性。</p>
<p>gpars是Java和Groovy都可以使用的并行编程库，他实现了Actor、Agent、DataFlow等模型，旨在为Groovy提供高层的并行编程模型。以下分析gpars 0.12中非阻塞Actor的实现。</p>
<div class="codecolorer-container groovy twitlight" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="groovy codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">@Grab<span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">&quot;org.codehaus.gpars:gpars:0.11&quot;</span><span style="color: #66cc66;">&#41;</span><br />
<a href="http://www.google.de/search?q=site%3Agroovy.codehaus.org/%20import"><span style="color: #000000; font-weight: bold;">import</span></a> <span style="color: #a1a100;">groovyx.gpars.actor.Actors</span><br />
<br />
<a href="http://www.google.de/search?q=site%3Agroovy.codehaus.org/%20def"><span style="color: #000000; font-weight: bold;">def</span></a> worker <span style="color: #66cc66;">=</span> Actors.<span style="color: #006600;">actor</span> <span style="color: #66cc66;">&#123;</span><br />
&nbsp; &nbsp; loop <span style="color: #66cc66;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; react <span style="color: #66cc66;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; reply it.<a href="http://www.google.de/search?q=site%3Agroovy.codehaus.org/%20reverse"><span style="color: #663399;">reverse</span></a><span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #66cc66;">&#125;</span><br />
&nbsp; &nbsp; <span style="color: #66cc66;">&#125;</span><br />
<span style="color: #66cc66;">&#125;</span><br />
<br />
<a href="http://www.google.de/search?q=site%3Agroovy.codehaus.org/%20def"><span style="color: #000000; font-weight: bold;">def</span></a> console <span style="color: #66cc66;">=</span> Actors.<span style="color: #006600;">actor</span> <span style="color: #66cc66;">&#123;</span><br />
&nbsp; &nbsp; worker <span style="color: #66cc66;">&lt;&lt;</span> <span style="color: #ff0000;">&quot;Hello GPars&quot;</span><br />
&nbsp; &nbsp; react <span style="color: #66cc66;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <a href="http://www.google.de/search?q=site%3Agroovy.codehaus.org/%20println"><span style="color: #993399;">println</span></a> it<br />
&nbsp; &nbsp; <span style="color: #66cc66;">&#125;</span><br />
<span style="color: #66cc66;">&#125;</span><br />
<br />
console.<a href="http://www.google.de/search?q=site%3Agroovy.codehaus.org/%20join"><span style="color: #663399;">join</span></a><span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span></div></div>
<p>首先，在工厂类中Actors里会初始化一个DefaultPGroup用来封装后台的线程池、管理actors。Actors默认使用ResizeablePool，他是JDK Concurrent Framework中的ThreadPoolExecutor的封装，coreSize和maxSize不同所以称Resizeable。</p>
<p>Actors的工厂方法actor生成的是DefaultActor，它是非阻塞actor的默认实现。（ActorGroup:67）</p>
<p>DefaultActor的构造方法接受一个Groovy的闭包对象，将其封装为DefaultActorClosure对象后，调用其父类AbstractLoopingActor的initialize方法（DefaultActor：73）.</p>
<p>initialize方法创建一个Runnable对象AsyncMessagingCore，并将线程池传递给core对象。（AbstractLoopingActor:57）AsyncMessagingCore对象负责消息的传递和处理，是线程池处理的目标对象。</p>
<p>调用start启动actor后，actor会向自己发送一个start消息（AbstractLoopingActor:173）.<br />
core获得start消息后，调用DefaultActor覆盖的handleStart方法（DefaultActor:328）。</p>
<p>在handleStart中，actor会调用用户传入的闭包方法。上面的例子是一种典型的用法，loop是DefaultActor中的方法，loop也并不是无限空转的，他仅在收到消息被时被触发（DefaultActor:191）react也是DefaultActor中的方法，它将nextContinuation方法设为内部闭包对象，用来处理actor接收的消息。</p>
<p>向Actor发送消息，是通过actor的send方法和重载的leftShift运算符进行操作。（AbstractLoopingActor:236）actor调用core的store方法，将ActorMessage压入core的队列中。入队列之后，core会检查锁对象activeUpdater，判断当前core是否在线程处理中，如果不在，则将core加入线程池中处理。activeUpdater是一个AtomicIntegerFieldUpdater对象，他的compareAndSet可以保证原子性。而通过activeUpdater也可以保证同一时刻只有一个core被线程池处理，从而使actor的线程不安全代码也线程安全地运行。</p>
<p>进入线程池后，core首先将自己放进threadlocal对象中，并保存当前线程的引用。然后会循环消费MessageQueue中的消息直至Queue的可处理部分为空。（AsyncMessagingCore:126）。handleMessage在AbstractLoopingActor中被覆盖，会根据消息的类型进行分发调用（前面提到的start消息就是一种）。默认的业务消息，在DefaultActorClojure中调用DefaultActor的onMessage方法处理。</p>
<p>onMessage中，react的闭包会被调用来处理业务。之后nextContinuation被置为null，这时loop闭包被重新调用，react闭包重新被赋给nextContinuation。这部分代码就是前面所说的loop并非空转，而是在消息处理完成后重新准备而已。</p>
<p>此外，core的MessageQueue的实现是DefaultMessageQueue。它使用两个LinkedList作为输入（向actor输入）队列和输出队列，当输入队列为空时，通过同步方法swap交换输入输出队列。swap是整个actor系统里唯一一个同步方法。这样的机制保证actor的core在线程池中处理时，外界仍然可以向actor发送消息，消息会在actor被调度出线程池之前全部处理掉。不过，他的前提是只有一个线程读这个队列，这个条件在actor系统里，通过core对象的activeUpdater可以有效的保证。</p>
<p>Actor模式采用这种onDemand方式的线程使用，允许大量的actor共存，并只有活跃的actor会占用线程，非活跃状态的actor处在dettach状态，并不消耗计算资源，取消了空转的loop。</p>
]]></content:encoded>
			<wfw:commentRss>http://sunng.info/blog/2011/04/gpars%e7%9a%84actor%e5%ae%9e%e7%8e%b0/feed/</wfw:commentRss>
		<slash:comments>7</slash:comments>
		</item>
		<item>
		<title>geb for browser functional testing</title>
		<link>http://sunng.info/blog/2010/08/geb-for-browser-functional-testing/</link>
		<comments>http://sunng.info/blog/2010/08/geb-for-browser-functional-testing/#comments</comments>
		<pubDate>Tue, 17 Aug 2010 14:42:14 +0000</pubDate>
		<dc:creator>sunng</dc:creator>
				<category><![CDATA[装备]]></category>
		<category><![CDATA[groovy]]></category>
		<category><![CDATA[Testing]]></category>
		<category><![CDATA[web]]></category>

		<guid isPermaLink="false">http://sunng.info/blog/2010/08/geb-for-browser-functional-test/</guid>
		<description><![CDATA[虽然现在不做前段了，但是发现好的工具还是很兴奋。今天在twitter上看到Grails in Action的作者 @pledbrook 转了一个geb 0.4的消息，顺带看了一下这个工具 http://geb.codehaus.org geb项目旨在创造一套groovy dsl帮助人们进行webapp的functional test。它是对selenium的封装，举例： @Grapes&#40;&#91; &#160; &#160; @Grab&#40;'org.seleniumhq.selenium:selenium-firefox-driver:latest.release'&#41;, &#160; &#160; @Grab&#40;'org.codehaus.geb:geb-core:latest.release'&#41; &#93;&#41; import geb.* println &#34;Dependencies downloaded, ready for testing&#34; Browser.drive&#40;'http://sunng.info:8000/Pacajus'&#41;&#123; &#160; &#160; assert title== 'Pacajus' &#160; &#160; assert $&#40;&#34;p&#34;, 3&#41;.text&#40;&#41; == 'Population: 41558' &#8230; <a href="http://sunng.info/blog/2010/08/geb-for-browser-functional-testing/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>虽然现在不做前段了，但是发现好的工具还是很兴奋。今天在twitter上看到Grails in Action的作者 @pledbrook 转了一个geb 0.4的消息，顺带看了一下这个工具</p>
<p>http://geb.codehaus.org</p>
<p>geb项目旨在创造一套groovy dsl帮助人们进行webapp的functional test。它是对selenium的封装，举例：</p>
<div class="codecolorer-container groovy twitlight" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="groovy codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">@Grapes<span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#91;</span><br />
&nbsp; &nbsp; @Grab<span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">'org.seleniumhq.selenium:selenium-firefox-driver:latest.release'</span><span style="color: #66cc66;">&#41;</span>,<br />
&nbsp; &nbsp; @Grab<span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">'org.codehaus.geb:geb-core:latest.release'</span><span style="color: #66cc66;">&#41;</span><br />
<span style="color: #66cc66;">&#93;</span><span style="color: #66cc66;">&#41;</span><br />
<a href="http://www.google.de/search?q=site%3Agroovy.codehaus.org/%20import"><span style="color: #000000; font-weight: bold;">import</span></a> <span style="color: #a1a100;">geb.*</span><br />
<br />
<a href="http://www.google.de/search?q=site%3Agroovy.codehaus.org/%20println"><span style="color: #993399;">println</span></a> <span style="color: #ff0000;">&quot;Dependencies downloaded, ready for testing&quot;</span><br />
Browser.<span style="color: #006600;">drive</span><span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">'http://sunng.info:8000/Pacajus'</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#123;</span><br />
&nbsp; &nbsp; <a href="http://www.google.de/search?q=site%3Agroovy.codehaus.org/%20assert"><span style="color: #000000; font-weight: bold;">assert</span></a> title<span style="color: #66cc66;">==</span> <span style="color: #ff0000;">'Pacajus'</span><br />
<br />
&nbsp; &nbsp; <a href="http://www.google.de/search?q=site%3Agroovy.codehaus.org/%20assert"><span style="color: #000000; font-weight: bold;">assert</span></a> $<span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">&quot;p&quot;</span>, <span style="color: #cc66cc;">3</span><span style="color: #66cc66;">&#41;</span>.<span style="color: #006600;">text</span><span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">==</span> <span style="color: #ff0000;">'Population: 41558'</span><br />
<span style="color: #66cc66;">&#125;</span><br />
<a href="http://www.google.de/search?q=site%3Agroovy.codehaus.org/%20println"><span style="color: #993399;">println</span></a> <span style="color: #ff0000;">&quot;Tested, bye&quot;</span></div></div>
<p>打开页面，执行断言。如果断言失败，driver方法会报null：<br />
Caught: geb.error.DriveException: null</p>
<p>只要在命令行用groovy执行即可，grapes会搞定依赖关系。</p>
<p>很方便吧，文档上说还可以跟grails / junit等等集成，快去看看吧<br />
<a href="http://geb.codehaus.org/manual/latest/index.html">http://geb.codehaus.org/manual/latest/index.html</a></p>
<p>The post is brought to you by <a href="http://fedorahosted.org/lekhonee">lekhonee</a> v0.7</p>
]]></content:encoded>
			<wfw:commentRss>http://sunng.info/blog/2010/08/geb-for-browser-functional-testing/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Maven recipe #1: Test Java code with groovy</title>
		<link>http://sunng.info/blog/2010/05/maven-recipe-1-test-java-code-with-groovy/</link>
		<comments>http://sunng.info/blog/2010/05/maven-recipe-1-test-java-code-with-groovy/#comments</comments>
		<pubDate>Tue, 18 May 2010 17:43:40 +0000</pubDate>
		<dc:creator>sunng</dc:creator>
				<category><![CDATA[把戏]]></category>
		<category><![CDATA[groovy]]></category>
		<category><![CDATA[java]]></category>
		<category><![CDATA[maven]]></category>

		<guid isPermaLink="false">http://sunng.info/blog/?p=573</guid>
		<description><![CDATA[问题： 受够了，不想写Java了，写个含有数据的map还要new出来一个一个put进去，想用groovy解决单元测试 解决： gmaven+groovy eclipse插件可以解决这个需求 在pom.xml中添加gmaven的依赖，注意，仅用来测试。老大不让生产代码里有不可靠的东西。 ... &#160; &#160; &#160; &#160; &#60;dependency&#62; &#160; &#160; &#160; &#160; &#160; &#160; &#60;groupId&#62;org.codehaus.groovy.maven.runtime&#60;/groupId&#62; &#160; &#160; &#160; &#160; &#160; &#160; &#60;artifactId&#62;gmaven-runtime-default&#60;/artifactId&#62; &#160; &#160; &#160; &#160; &#160; &#160; &#60;version&#62;1.0-rc-3&#60;/version&#62; &#160; &#160; &#160; &#160; &#160; &#160; &#60;scope&#62;test&#60;/scope&#62; &#8230; <a href="http://sunng.info/blog/2010/05/maven-recipe-1-test-java-code-with-groovy/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>问题： 受够了，不想写Java了，写个含有数据的map还要new出来一个一个put进去，想用groovy解决单元测试<br />
解决： gmaven+groovy eclipse插件可以解决这个需求<br />
在pom.xml中添加gmaven的依赖，注意，仅用来测试。老大不让生产代码里有不可靠的东西。</p>
<div class="codecolorer-container xml twitlight" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="xml codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">...<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;dependency<span style="color: #000000; font-weight: bold;">&gt;</span></span></span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;groupId<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>org.codehaus.groovy.maven.runtime<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/groupId<span style="color: #000000; font-weight: bold;">&gt;</span></span></span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;artifactId<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>gmaven-runtime-default<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/artifactId<span style="color: #000000; font-weight: bold;">&gt;</span></span></span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;version<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>1.0-rc-3<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/version<span style="color: #000000; font-weight: bold;">&gt;</span></span></span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;scope<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>test<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/scope<span style="color: #000000; font-weight: bold;">&gt;</span></span></span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/dependency<span style="color: #000000; font-weight: bold;">&gt;</span></span></span><br />
...<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;plugin<span style="color: #000000; font-weight: bold;">&gt;</span></span></span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;groupId<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>org.codehaus.groovy.maven<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/groupId<span style="color: #000000; font-weight: bold;">&gt;</span></span></span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;artifactId<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>gmaven-plugin<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/artifactId<span style="color: #000000; font-weight: bold;">&gt;</span></span></span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;version<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>1.0-rc-3<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/version<span style="color: #000000; font-weight: bold;">&gt;</span></span></span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;executions<span style="color: #000000; font-weight: bold;">&gt;</span></span></span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;execution<span style="color: #000000; font-weight: bold;">&gt;</span></span></span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;goals<span style="color: #000000; font-weight: bold;">&gt;</span></span></span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;goal<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>generateStubs<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/goal<span style="color: #000000; font-weight: bold;">&gt;</span></span></span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;goal<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>compile<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/goal<span style="color: #000000; font-weight: bold;">&gt;</span></span></span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;goal<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>generateTestStubs<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/goal<span style="color: #000000; font-weight: bold;">&gt;</span></span></span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;goal<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>testCompile<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/goal<span style="color: #000000; font-weight: bold;">&gt;</span></span></span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/goals<span style="color: #000000; font-weight: bold;">&gt;</span></span></span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/execution<span style="color: #000000; font-weight: bold;">&gt;</span></span></span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/executions<span style="color: #000000; font-weight: bold;">&gt;</span></span></span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/plugin<span style="color: #000000; font-weight: bold;">&gt;</span></span></span></div></div>
<p>在eclipse中新建source folder, <em>src/test/groovy</em>，在其中创建groovy test case即可</p>
]]></content:encoded>
			<wfw:commentRss>http://sunng.info/blog/2010/05/maven-recipe-1-test-java-code-with-groovy/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Groovy http-builder tips</title>
		<link>http://sunng.info/blog/2009/11/groovy-http-builder-tips/</link>
		<comments>http://sunng.info/blog/2009/11/groovy-http-builder-tips/#comments</comments>
		<pubDate>Fri, 20 Nov 2009 06:53:36 +0000</pubDate>
		<dc:creator>sunng</dc:creator>
				<category><![CDATA[把戏]]></category>
		<category><![CDATA[groovy]]></category>
		<category><![CDATA[java]]></category>

		<guid isPermaLink="false">http://www.classicning.com/blog/?p=330</guid>
		<description><![CDATA[最近用Groovy的HttpBuilder模块开发RESTful服务的客户端，遇到不少问题，浪费不少时间 网上的例子都是从Grape开始的，但是按照例子上运行，无论是通过grape install还是在代码里@Grab都没有办法把http builder加到classpath里，甚至依赖关系已经下载到~/.groovy/grapes里了，但是还是在import的时候报错。用Grails的时候也是一样，如果通过ivy定义依赖，通过ant下载到lib目录中，在grails shell里还是没有办法引用。不理解了，难道还需要手动再指定path吗。最后用grails的rest插件（grails install-plugin rest）总算是下载到了path中了。 第二是http builder的报错太智能了，它会把服务器端50x的报错输出在客户端。在查看错误的时候一定要分清楚。 第三是net.sf.json-lib这个库在转json的时候有一点问题，比如这样的js对象 {&#8220;result&#8221;:&#8221;success&#8221;} 会因为key上有引号而无法解析，必须是这样的格式： {result: &#8220;success&#8221;} 至于那种是正确的json我也没有兴趣了解了，只是非常遗憾的是couchdb返回的都是前一种形式。 当然了，瑕不掩瑜，http builder还是提供了非常方便的封装，比直接用HttpURLConnection或是HttpClient更加Groovy]]></description>
			<content:encoded><![CDATA[<p>最近用Groovy的HttpBuilder模块开发RESTful服务的客户端，遇到不少问题，浪费不少时间</p>
<p>网上的例子都是从Grape开始的，但是按照例子上运行，无论是通过grape install还是在代码里@Grab都没有办法把http builder加到classpath里，甚至依赖关系已经下载到~/.groovy/grapes里了，但是还是在import的时候报错。用Grails的时候也是一样，如果通过ivy定义依赖，通过ant下载到lib目录中，在grails shell里还是没有办法引用。不理解了，难道还需要手动再指定path吗。最后用grails的rest插件（grails install-plugin rest）总算是下载到了path中了。</p>
<p>第二是http builder的报错太智能了，它会把服务器端50x的报错输出在客户端。在查看错误的时候一定要分清楚。</p>
<p>第三是net.sf.json-lib这个库在转json的时候有一点问题，比如这样的js对象<br />
<em>{&#8220;result&#8221;:&#8221;success&#8221;}</em></p>
<p>会因为key上有引号而无法解析，必须是这样的格式：<br />
<em>{result: &#8220;success&#8221;}</em></p>
<p>至于那种是正确的json我也没有兴趣了解了，只是非常遗憾的是couchdb返回的都是前一种形式。</p>
<p>当然了，瑕不掩瑜，http builder还是提供了非常方便的封装，比直接用HttpURLConnection或是HttpClient更加Groovy</p>
]]></content:encoded>
			<wfw:commentRss>http://sunng.info/blog/2009/11/groovy-http-builder-tips/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Mapping Geometry in Grails and MySQL</title>
		<link>http://sunng.info/blog/2009/10/mapping-geometry-in-grails-and-mysql/</link>
		<comments>http://sunng.info/blog/2009/10/mapping-geometry-in-grails-and-mysql/#comments</comments>
		<pubDate>Tue, 06 Oct 2009 11:14:36 +0000</pubDate>
		<dc:creator>sunng</dc:creator>
				<category><![CDATA[手艺]]></category>
		<category><![CDATA[GIS]]></category>
		<category><![CDATA[Grails]]></category>
		<category><![CDATA[groovy]]></category>
		<category><![CDATA[jts]]></category>
		<category><![CDATA[mysql]]></category>

		<guid isPermaLink="false">http://www.classicning.com/blog/?p=238</guid>
		<description><![CDATA[针对地理数据的ORM，有一个Hibernate的扩展HibernateSpatial项目可以将JTS对象映射到MySQL/PostGIS/Oracle中。这个扩展同样可以用在Grails里，这里有一篇简单的介绍，关于在Grails和MySQL中管理地理数据： http://www.grails.org/MySQL+GIS-Geometry+with+Grails 不过按照这个文章里介绍的方法用，很可能会遭遇这样的报错： org.hibernate.MappingException: No Dialect mapping for JDBC type: 2003 这个问题最终在这里得到了解答： http://n2.nabble.com/No-Dialect-mapping-for-JDBC-type-2003-td1141106.html 按照邮件列表里的反映，上面的配置在Postgis里是可以work的，但是如果用Mysql还需要指定JPA的columnDefinition，对应的Hibernate属性是sql-type。虽然作者承诺会在今后的版本里修改这个问题，不过眼下的M2版本还没有修正这个问题。为此，Grails的用户特地提出在Grails中加入sql-type的支持： http://jira.codehaus.org/browse/GRAILS-3201 现在按照下面文档的说明，可以在mapping里指定sqlType了： http://grails.org/doc/latest/ref/Database%20Mapping/column.html 实例代码里的domain定义应该改成： import com.vividsolutions.jts.geom.Polygon import org.hibernatespatial.GeometryUserType public class MyPoly { String name Polygon poly static mapping = { poly type: GeometryUserType， sqlType:"GEOMETRY" } } &#8230; <a href="http://sunng.info/blog/2009/10/mapping-geometry-in-grails-and-mysql/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>针对地理数据的ORM，有一个Hibernate的扩展<a href="http://www.hibernatespatial.org/" target="_blank">HibernateSpatial</a>项目可以将JTS对象映射到MySQL/PostGIS/Oracle中。这个扩展同样可以用在Grails里，这里有一篇简单的介绍，关于在Grails和MySQL中管理地理数据：<br />
<a href="http://www.grails.org/MySQL+GIS-Geometry+with+Grails" target="_blank">http://www.grails.org/MySQL+GIS-Geometry+with+Grails</a></p>
<p>不过按照这个文章里介绍的方法用，很可能会遭遇这样的报错：</p>
<blockquote><p>org.hibernate.MappingException: No Dialect mapping for JDBC type: 2003</p></blockquote>
<p>这个问题最终在这里得到了解答：<br />
<a href="http://n2.nabble.com/No-Dialect-mapping-for-JDBC-type-2003-td1141106.html" target="_blank">http://n2.nabble.com/No-Dialect-mapping-for-JDBC-type-2003-td1141106.html</a><br />
按照邮件列表里的反映，上面的配置在Postgis里是可以work的，但是如果用Mysql还需要指定JPA的columnDefinition，对应的Hibernate属性是sql-type。虽然作者承诺会在今后的版本里修改这个问题，不过眼下的M2版本还没有修正这个问题。为此，Grails的用户特地提出在Grails中加入sql-type的支持：<br />
<a href="http://jira.codehaus.org/browse/GRAILS-3201" target="_blank">http://jira.codehaus.org/browse/GRAILS-3201</a><br />
现在按照下面文档的说明，可以在mapping里指定sqlType了：<br />
<a href="http://grails.org/doc/latest/ref/Database%20Mapping/column.html" target="_blank">http://grails.org/doc/latest/ref/Database%20Mapping/column.html</a></p>
<p>实例代码里的domain定义应该改成：</p>
<pre class="brush:groovy">
import com.vividsolutions.jts.geom.Polygon
import org.hibernatespatial.GeometryUserType

public class MyPoly {
    String name
    Polygon poly

    static mapping = {
        poly type: GeometryUserType， sqlType:"GEOMETRY"
    }

}
</pre>
<p>于是，再也没有莫名其妙的No Dialect报错了。</p>
]]></content:encoded>
			<wfw:commentRss>http://sunng.info/blog/2009/10/mapping-geometry-in-grails-and-mysql/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Reading GPS Data From EXIF Using Groovy</title>
		<link>http://sunng.info/blog/2009/10/reading-gps-data-from-exif-using-groovy/</link>
		<comments>http://sunng.info/blog/2009/10/reading-gps-data-from-exif-using-groovy/#comments</comments>
		<pubDate>Mon, 05 Oct 2009 15:29:10 +0000</pubDate>
		<dc:creator>sunng</dc:creator>
				<category><![CDATA[手艺]]></category>
		<category><![CDATA[GIS]]></category>
		<category><![CDATA[groovy]]></category>
		<category><![CDATA[java]]></category>

		<guid isPermaLink="false">http://www.classicning.com/blog/?p=232</guid>
		<description><![CDATA[废话不说了，直接上code吧： import com.drew.imaging.jpeg.*; import com.drew.metadata.*; import com.drew.metadata.exif.*; file = new File("sample.jpg"); meta = JpegMetadataReader.readMetadata(file); gpsdir = meta.getDirectory(GpsDirectory.class); lat = gpsdir.getRationalArray(GpsDirectory.TAG_GPS_LATITUDE); lon = gpsdir.getRationalArray(GpsDirectory.TAG_GPS_LONGITUDE); lats = lat[0].doubleValue() + lat[1].doubleValue()/60 + lat[2].doubleValue()/3600; lons = lon[0].doubleValue() + lon[1].doubleValue()/60 + lon[2].doubleValue()/3600; println(lats); println(lons); metadata-extractor似乎是现在惟一的读取exif信息的java库。在ivy中可以添加这样一个依赖： &#8230; <a href="http://sunng.info/blog/2009/10/reading-gps-data-from-exif-using-groovy/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>废话不说了，直接上code吧：</p>
<pre class="brush:groovy">
import com.drew.imaging.jpeg.*;
import com.drew.metadata.*;
import com.drew.metadata.exif.*;

file = new File("sample.jpg");
meta = JpegMetadataReader.readMetadata(file);

gpsdir = meta.getDirectory(GpsDirectory.class);
lat = gpsdir.getRationalArray(GpsDirectory.TAG_GPS_LATITUDE);
lon = gpsdir.getRationalArray(GpsDirectory.TAG_GPS_LONGITUDE);
lats = lat[0].doubleValue() + lat[1].doubleValue()/60 + lat[2].doubleValue()/3600;
lons = lon[0].doubleValue() + lon[1].doubleValue()/60 + lon[2].doubleValue()/3600;
println(lats);
println(lons);
</pre>
<p>metadata-extractor似乎是现在惟一的读取exif信息的java库。在ivy中可以添加这样一个依赖：</p>
<pre class="brush:xml">
&lt;dependency org=&quot;com.drewnoakes&quot; name=&quot;metadata-extractor&quot; rev=&quot;2.4.0-beta-1&quot; conf=&quot;runtime&quot;/&gt;
</pre>
]]></content:encoded>
			<wfw:commentRss>http://sunng.info/blog/2009/10/reading-gps-data-from-exif-using-groovy/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
	</channel>
</rss>

