tag:blogger.com,1999:blog-32556926234135034882023-11-15T16:34:04.107+01:00Ramblings of a Java DudeJeroen van Erphttp://www.blogger.com/profile/09896622705281991146noreply@blogger.comBlogger13125tag:blogger.com,1999:blog-3255692623413503488.post-21892543834912173382011-02-22T14:43:00.003+01:002011-02-22T14:58:20.230+01:00Gradle License PluginOver at <a href="http://www.xebialabs.com">Xebialabs</a>, we've made the switch from Maven to Gradle. This means that a big part of the build is now much cleaner than it ever was with Maven. However working for a product company also entails dealing with software licenses.<a name='more'></a><br /><br />We of course have a license for our product (<a href="http://www.xebialabs.com/xebialabs-delivers-new-deployment-automation-solution-deployit-3-0">Deployit</a>). As with every license type, we want to have a header on top of all of our source files, stating our copyright. Now there are of course a number of 'simple' solutions for this, such as to adapt the templates provided by your favorite IDE. But then you setup your workspace again, and *poof* all your settings are gone.<br /><br />So for that we had the Maven license plugin in place, which during a release would 'brand' all our source files. With the switch to Gradle we didn't have this functionality anymore, so I decided to write the <a href="http://github.com/hierynomus/gradle-plugins">gradle-license-plugin</a> and open source it. It's usage is described in the README file on github. Feel free to fork and extend it. Would love to see some pull requests for nice features.Jeroen van Erphttp://www.blogger.com/profile/09896622705281991146noreply@blogger.com0tag:blogger.com,1999:blog-3255692623413503488.post-81606865078114038002010-09-16T16:43:00.006+02:002010-09-17T09:22:07.616+02:00Customizing Eclipse files with GradleCurrently I'm employed at <a href="http://www.xebialabs.com">XebiaLabs</a> where we're building our Deployit product. In the team, we recently switched from Maven2 to Gradle to build Deployit, so that we could do some funky stuff with integration testing our flash UI. However some of my team-members are now missing certain magic features from m2eclipse... <a name='more'></a><br /><br />When you use m2eclipse, it will not only detect all the real modules of your build. But also any other projects which are in your Eclipse workspace. We for instance have some 3rd party plugins for Deployit, which reside outside of our normal build and are in a plugins tree somewhere else. However when we run:<br /><pre name="code"><br />$ gradle eclipse<br /></pre><br />On our projects, it won't resolve these dependencies as they are not part of the multi-module build. Sounds like a nice problem to tackle with Gradle, as it is possible to customize just about anything.<br /><br />After browsing through the documentation a bit, I started out with something like:<br /><pre name="code" lang="java"><br />subprojects {<br /> apply plugin: 'eclipse'<br /> ...<br /><br /> eclipseClasspath {<br /> ...<br /> }}<br /></pre><br />Which was suggested in the <a href="http://www.gradle.org/0.9-rc-1/docs/userguide/eclipse_plugin.html">documentation</a> of the Gradle Eclipse plugin. However that gave me a MethodMissingException for "eclipseClasspath". So I applied the following trick to get it all to work:<br /><br /><pre name="code" lang="java"><br />subprojects {<br /> apply plugin: 'eclipse'<br /> ...<br /><br /> afterEvaluate { eachProject -><br /> eachProject.tasks.withType(org.gradle.plugins.eclipse.EclipseClasspath).each { task -><br /> task.whenConfigured { classpath -><br /> groupDependencies = classpath.entries.findAll { entry -> entry.path.contains(project.group)}<br /> classpath.entries.removeAll(groupDependencies)<br /> groupDependencies.each { dep -><br /> projectName = "/" + dep.sourcePath.split("/")[2]<br /> if (classpath.entries.findAll({ entry -> entry.path.equals(projectName) }).isEmpty()) {<br /> newProject = new org.gradle.plugins.eclipse.model.ProjectDependency(projectName, true, null, new HashSet())<br /> classpath.entries.add(newProject)<br /> }}}}}}<br /></pre><br /><br />What this does is scan for all dependencies which have the same group as our current project, and replace them with ProjectDependencies if that hasn't been done before. <br /><br />If anyone knows how to do this without doing the afterEvaluate trick and looking up the tasks, I'd be happy to see a comment. For now it seems to work, and my colleagues are somewhat happier with Gradle again ;-)...Jeroen van Erphttp://www.blogger.com/profile/09896622705281991146noreply@blogger.com1tag:blogger.com,1999:blog-3255692623413503488.post-58513420197839778932010-09-14T22:00:00.004+02:002010-09-16T16:43:54.009+02:00Gradle and IntelliJ (revisited)In one of my <a href="http://www.javadude.nl/2010/03/gradle-and-intellij-idea.html">previous posts</a>, I described a way of importing Gradle projects with IntelliJ IDEA. However with the release of Gradle 0.9 rc-1, there is a new way of doing this!<br /><a name='more'></a><br />In you build file you can just add the following plugin:<br /><pre name="code" class="java"><br />apply plugin: "idea"<br /></pre><br /><br />Now if you run the "gradle idea" command, Gradle with generate your IntelliJ IDEA project files, and you can open the project.Jeroen van Erphttp://www.blogger.com/profile/09896622705281991146noreply@blogger.com0tag:blogger.com,1999:blog-3255692623413503488.post-4116550658239786202010-06-07T16:31:00.000+02:002010-09-13T14:16:14.472+02:00Timing Seam InjectionOne of the main concepts in Seam is the Bijection of Components. Seam can inject components into eachother and can outject them for use in for instance XHTML pages. However, bijection takes time, how much time is mainly dependent on how much dependencies need to be loaded. However, normally you cannot easily measure the overhead time of bijection.<a name='more'></a><br /><br />In order to facilitate bijection, Seam wraps components in an interceptor called the BijectionInterceptor. Luckily Seam provides an Interceptor chain, which we can use to wrap another interceptor around the BijectionInterceptor so that we can actually measure execution time, including the bijection overhead. Let's start with the interceptor:<br /><br /><pre name="code" class="java"><br />import org.jboss.seam.Component;<br />import org.jboss.seam.annotations.intercept.AroundInvoke;<br />import org.jboss.seam.annotations.intercept.Interceptor;<br />import org.jboss.seam.core.BijectionInterceptor;<br />import org.jboss.seam.intercept.AbstractInterceptor;<br />import org.jboss.seam.intercept.InvocationContext;<br />import org.slf4j.Logger;<br />import org.slf4j.LoggerFactory;<br /><br />/**<br />* Measuring tool for injection calls.<br />*/<br />@Interceptor(around = BijectionInterceptor.class, stateless = true)<br />public class TimingInterceptor extends AbstractInterceptor {<br /> private static final long serialVersionUID = 5274243063215400992L;<br /> private static final Logger log = LoggerFactory.getLogger(TimingInterceptor.class);<br /><br /> /**<br /> * Measure the timing of injection calls.<br /> * @param ic The Invocation Context.<br /> * @return The return value of the invocation.<br /> * @throws Exception Throws any exception which occurs in the invocationContext.<br /> */<br /> @AroundInvoke<br /> public Object aroundInvoke(InvocationContext ic) throws Exception {<br /> String componentName = getComponent().getName();<br /> componentName += "." + ic.getMethod().getName();<br /> long milliStart = System.currentTimeMillis();<br /> Object o = null;<br /> try {<br /> o = ic.proceed();<br /> } finally {<br /> log.debug("Execution of {} took {} millis", componentName, System.currentTimeMillis() - milliStart);<br /> }<br /> return o;<br /> }<br /><br /> /**<br /> * This interceptor is ALWAYS enabled.<br /> * @return true.<br /> */<br /> public boolean isInterceptorEnabled() {<br /> return true;<br /> }<br />}<br /></pre><br /><br />This interceptor can effectively measure the time spent in the full call, including the bijection process. With the @Interceptor annotation we have specified that the TimerInterceptor should be wrapped around the BijectionInterceptor.<br /><br />We must now instruct Seam to use our interceptor. Seam can discover that it needs to wrap an invocation to a method with our interceptor if an annotation is present which references the interceptor. So let's write such an annotation:<br /><br /><pre name="code" class="java"><br />import java.lang.annotation.ElementType;<br />import java.lang.annotation.Retention;<br />import java.lang.annotation.RetentionPolicy;<br />import java.lang.annotation.Target;<br /><br />import org.jboss.seam.annotations.intercept.Interceptors;<br /><br />/**<br />* Annotation that specifies whether calls to a certain Seam component are timed.<br />*/<br />@Target(ElementType.TYPE)<br />@Retention(RetentionPolicy.RUNTIME)<br />@Interceptors(TimingInterceptor.class)<br />public @interface Timed {<br />}<br /></pre><br /><br />The @Timed annotation is annotated with @Interceptors, which specifies which interceptors it needs in the interceptor chain. By referencing the TimingInterceptor here, we instruct Seam to use that one when the component is annotated with @Timed. Once you do that, you will be able to see how many milliseconds are spent in the total execution of a method of that component.Jeroen van Erphttp://www.blogger.com/profile/09896622705281991146noreply@blogger.com1tag:blogger.com,1999:blog-3255692623413503488.post-81846826539360162842010-05-21T15:37:00.000+02:002010-09-13T14:25:46.287+02:00Revised Seam Application Scoped RepositoriesIn <a href="http://www.javadude.nl/java/seam-application-scoped-repositories/">yesterdays blog</a> I wrote about repositories in a Seam application that have application scope. In this blog I also presented a possible solution. In this blog I wish to present a better solution that also makes use of the Seam Managed Persistence Contexts.<br /><a name='more'></a><br /><br />Seam has a way to manage your persistence context (Hibernate Session) for you, so that you don't need to care about the dreaded <i>LazyInitializationException</i>. Seam does this via the Seam Managed Persistence Context. This is a built in Seam component that maintains a (Hibernate) Session for you in the Conversation context. However as our Repositories are Application context scoped, they are a singleton and thus we cannot inject the Session in them.<br /><br />In our approach from yesterday, we broke this feature, because we obtained our own session from the SessionFactory (which was injected by Seam), and closing that session. Luckily Seam has a way to programmatically obtain any component. Let's have a look at a new solution to this problem:<br /><br /><pre name="code" class="java"><br />@Name("petRepository")<br />@Scope(ScopeType.APPLICATION)<br />@AutoCreate<br />public class HibernatePetRepository implements PetRepository {<br /><br /> public List<Pet> loadSomePets() {<br /> Session session = (Session) Component.getInstance("hibernateSession");<br /> return session.createQuery("from Pet").list();<br /> }<br /><br /> ... omitted methods ...<br />}<br /></pre><br /><br />In this way, we obtain the Session for the specific Conversation or request of the user.Jeroen van Erphttp://www.blogger.com/profile/09896622705281991146noreply@blogger.com0tag:blogger.com,1999:blog-3255692623413503488.post-55629574686845892012010-05-20T16:12:00.000+02:002010-09-13T15:03:39.870+02:00Seam Application Scoped RepositoriesSometimes bugs are so obvious that they hit your blind spot. This happened to me last day, while working on a Seam project at one of our customers. I was writing JMeter tests as part of the QA team to stress test the application, and I got some weird exceptions...<br /><a name='more'></a><br />As soon as I went beyond the point of a single user hitting the application, I would at random get "Connection closed" or "Session already closed" exceptions from Hibernate.<br /><br />As our (Hibernate) sessions are managed by Seam, my guess was that we were getting back stale connections from our connection pool. After removing that, and disabling all the cacheing, the exceptions seemed to occur less, but they were not gone.<br /><br />So now I needed to get my hands dirty and take a deep dive in our code to see what was really the issue here. I started out by looking at our components.xml file, which contains the Seam managed components. In it we have configured the Hibernate SessionFactory and (managed) Hibernate Session.<br /><br /><textarea name="code" class="xml"><br /><components xmlns="http://jboss.com/products/seam/components"<br /> xmlns:persistence="http://jboss.com/products/seam/persistence"<br /> xsi:schemaLocation="<br /> http://jboss.com/products/seam/components http://jboss.com/products/seam/components-2.2.xsd<br /> http://jboss.com/products/seam/persistence http://jboss.com/products/seam/persistence-2.2.xsd"><br /><br /> <persistence:hibernate-session-factory<br /> name="sessionFactory" cfg-resource-name="hibernate.cfg.xml"/><br /><br /> <persistence:managed-hibernate-session name="hibernateSession" session-factory="#{sessionFactory}" auto-create="true"/><br /><br />....<br /></components><br /></textarea><br /><br />And the Repository code, which deals with Hibernate looks like the following<br /><br /><pre name="code" class="java"><br />@Name("petRepository")<br />@Scope(ScopeType.APPLICATION)<br />@AutoCreate<br />public class HibernatePetRepository implements PetRepository {<br /> @In<br /> private Session hibernateSession;<br /><br /> public List<Pet> loadSomePets() {<br /> return hibernateSession.createQuery("from Pet").list();<br /> }<br /><br /> ... omitted methods ...<br />}<br /></pre><br /><br />This looks ok, right.... Ok, now wait a minute, go back a few lines... We've Application scoped our Repository component, and we've injected it with a hibernate Session. That can't be right. A Repository should be stateless, and a Session is state. Once you start hitting the application with a few users, you will get random threading issues. Instead we should have created the repository as such:<br /><br /><pre name="code" class="java"><br />@Name("petRepository")<br />@Scope(ScopeType.APPLICATION)<br />@AutoCreate<br />public class HibernatePetRepository implements PetRepository {<br /> @In<br /> private SessionFactory sessionFactory;<br /><br /> public List<Pet> loadSomePets() {<br /> Session session = null;<br /> try {<br /> session = sessionFactory.openSession();<br /> return session.createQuery("from Pet").list();<br /> } finally {<br /> if (session != null) {<br /> session.close();<br /> }<br /> }<br /> }<br /><br /> ... omitted methods ...<br />}<br /></pre><br /><br />Now our repository is threadsafe again, and can thus safely be used in the application!Jeroen van Erphttp://www.blogger.com/profile/09896622705281991146noreply@blogger.com1tag:blogger.com,1999:blog-3255692623413503488.post-91086217599423384422010-05-12T13:27:00.000+02:002010-09-13T16:28:44.456+02:00The Gradle WrapperWho hasn't come across build system version incompatibilities? You build your system with Maven 2.0.X and one of your colleagues with 2.0.Y, and one of your builds break. Gradle provides a way to circumvent this, the <em>Gradle Wrapper</em>.<br /><a name='more'></a><br /><br />In Gradle you can have your project generate a gradle wrapper (gradlew) which you can commit to your repository. All subsequent build(er)s should then just execute:<br /><pre name="code"><br />$ ./gradlew<br /></pre><br /><br />But how do you generate this? In the new gradle 0.9, the following snipplet generates the wrapper for you:<br /><br /><pre name="code" lang="java"><br />task wrapper(type: Wrapper) {<br /> gradleVersion = '0.9-preview-1'<br />}<br /></pre><br /><br />When you as the build-master now execute <em>gradle wrapper</em>, the buildprocess will generate the following files in the project:<br /><br /><ul><br /><li>gradle-wrapper.jar</li><br /><li>gradle-wrapper.properties</li><br /><li>gradlew</li><br /><li>gradlew.bat</li><br /></ul><br /><br />Now what does executing the gradlew command do? It first determines whether you have the right version (if any) installed of Gradle. If you do not have that, it downloads it for you. Once that's done, it will build the project using the right version of Gradle, all the time! If the build-master decides that the Gradle version should be bumped, he can edit the task and generate a new wrapper. Each of the people building the project then automatically pick this up.Jeroen van Erphttp://www.blogger.com/profile/09896622705281991146noreply@blogger.com0tag:blogger.com,1999:blog-3255692623413503488.post-70910660531381367812010-04-22T12:06:00.000+02:002010-09-14T10:06:23.796+02:00Using the Google AppEngine Gradle PluginIn my previous blog post, I described the <a href="http://www.javadude.nl/build-tools/appengine-gradle-plugin/">Google AppEngine Plugin for Gradle</a>. In this blog I will show you how you can use it to deploy your own applications to Google AppEngine.<br /><a name='more'></a><br /><br />FIrst thing you need to do, in order to use the plugin, is to add it to your buildfile. Because this plugin is not in the list of standard gradle plugins, you need to pass a closure to the buildscript method. Everything that you add there will be executed before your actual buildscript is invoked. So in essence you can add some set-up information there, which is exactly what we want. Let's look at what should be added to the build.gradle file:<br /><br /><pre name="code" class="java"><br />buildscript {<br /> repositories {<br /> mavenRepo urls: 'file:///tmp/'<br /> add(new org.apache.ivy.plugins.resolver.URLResolver()) {<br /> name = "GitHub"<br /> addArtifactPattern 'http://github.com/hierynomus/appengine-gradle-plugin/downloads/[organization]-[module]-[revision].[ext]'<br /> }<br /> }<br /><br /> dependencies {<br /> classpath 'com.xebia:appengine-gradle-plugin:0.2@jar'<br /> classpath 'appengine:tools-api:1.3.2@jar'<br /> }<br />}<br /></pre><br /><br />Now we can add the plugin to our gradle buildfile:<br /><br /><pre name="code" class="java"><br />buildscript { ... }<br /><br />defaultTasks 'build'<br />usePlugin 'war'<br />usePlugin com.xebia.gradle.plugins.AppEngine<br /></pre><br /><br />You are now almost ready to use the plugin. One thing left to do is add a properties file to the root of your build directory. In this property file we will denote the location of the Google AppEngine SDK, which is needed by the AppEngine Tools which are used under the hood.<br /><br /><pre name="code" class="properties"><br />appEngineSdkRoot=<path to appengine sdk><br /></pre><br /><br />Once you're done, and your application is setup to the AppEngine guidelines, it is just a matter of running the following command:<br /><br /><pre name="code" class="bash"><br />$ gradle upload<br /></pre><br /><br />After that you can see in your AppEngine dashboard that the plugin uploaded a new version of your application<br /><a href="http://www.javadude.nl/wp-content/uploads/Schermafbeelding-2010-04-16-om-15.51.27.png"><img src="http://www.javadude.nl/wp-content/uploads/Schermafbeelding-2010-04-16-om-15.51.27-300x41.png" alt="" title="AppEngine dashboard" width="300" height="41" class="alignnone size-medium wp-image-44" /></a>Jeroen van Erphttp://www.blogger.com/profile/09896622705281991146noreply@blogger.com0tag:blogger.com,1999:blog-3255692623413503488.post-57509080281471101442010-04-19T09:25:00.000+02:002010-09-14T10:06:51.149+02:00AppEngine Gradle PluginLast Friday I worked on a <a href="http://github.com/asikkema/adoptimizer">pet project</a> together with some colleagues. We're building the project with Gradle and we wanted to deploy it to Google AppEngine. Now Gradle has support for plugins, so I decided I'd build a plugin for Google AppEngine....<a name='more'></a><br /><br />Creating plugins for Gradle isn't half as hard a creating one for Maven2. You can setup a simple project, I choose groovy, add a gradle build file, and implement a single interface... Let's start with the buildfile:<br /><br /><pre name="code" class="java"><br />defaultTasks "clean", "build"<br /><br />usePlugin 'groovy'<br /><br />group = 'com.xebia'<br />version = '0.2'<br /><br />repositories {<br /> add(new org.apache.ivy.plugins.resolver.URLResolver()) {<br /> name = "GitHub"<br /> addArtifactPattern 'http://github.com/hierynomus/appengine-gradle-plugin/downloads/[organization]-[module]-[revision].[ext]'<br /> }<br />}<br /><br />dependencies {<br /> groovy "appengine:tools-api:1.3.2@jar"<br /> groovy fileTree(dir: new File(gradle.gradleHomeDir, 'lib'), includes: ['*.jar'])<br />}<br /></pre><br /><br />As you see, the buildfile is nothing special, it looks just like an ordinary Gradle project buildfile. We use the 'groovy' plugin, as our plugin will be written using groovy. Also we use 'fileTree' to add all the gradle jars to the classpath of our plugin.<br /><br />Next up, the plugin code.<br /><br /><pre name="code" class="java"><br />import com.google.appengine.tools.admin.AppCfg<br /><br />class AppEngine implements Plugin {<br /> void use(Project project, ProjectPluginsContainer pluginContainer) {<br /> // Configure the war plugin to explode the built war file.<br /> configureWarPlugin(project)<br /><br /> project.convention.plugins.appengine = new AppEnginePluginConvention(project)<br /> <br /> // The upload task, to upload to AppEngine<br /> project.task('upload') << {<br /> AppCfg.main("update", project.convention.plugins.appengine.exploded.toString())<br /> }<br /><br /> // Make sure that we built the war before uploading<br /> project.upload.dependsOn project.war<br /> }<br />}<br /></pre><br /><br />As you can see it is a very concise class that implements the org.gradle.api.Plugin interface. There are onl three other pieces of code to show. First we need to check whether the 'war' plugin was loaded and configure it to explode the WAR archive, as that is how AppEngine likes it.<br /><br /><pre name="code" class="java"><br /> def configureWarPlugin(Project project) {<br /> if (!project.plugins.hasPlugin('war')) {<br /> throw new InvalidUserDataException("For AppEngine plugin, the war plugin should be enabled!")<br /> }<br /><br /> // Add the exploded-war to the war task<br /> project.war.doLast {<br /> ant.unzip(src: project.war.archivePath, dest: project.convention.plugins.appengine.exploded)<br /> }<br /> }<br /></pre><br /><br />The other part is the so-called PluginConvention object. In this object we can store settings that are copied from your project build file when you're building the project and using our plugin. In our case we use it to read a properties file that tells us where the Google AppEngine SDK is located.<br /><br /><pre name="code" class="java"><br />class AppEnginePluginConvention {<br /> Properties props = new Properties()<br /> Project project<br /> File exploded<br /><br /> def AppEnginePluginConvention(project) {<br /> this.project = project<br /> if (!new File("appengine.properties").exists()) {<br /> throw new InvalidUserDataException("appengine.properties should exist in build root dir")<br /> }<br /> props.load(new FileInputStream("appengine.properties"))<br /> init()<br /> }<br /><br /> def init() {<br /> exploded = new File(project.buildDir, "exploded-war")<br /> System.setProperty("appengine.sdk.root", appEngineSdkRoot)<br /> }<br /><br /> def propertyMissing(String name) { props[name] }<br />}<br /></pre><br /><br />In another blog I will describe how you can use this plugin in a project. The code can be found on <a href="http://github.com/hierynomus/appengine-gradle-plugin">GitHub</a>. The plugin is still under development to add other AppEngine tasks to it, such as starting the development server.Jeroen van Erphttp://www.blogger.com/profile/09896622705281991146noreply@blogger.com1tag:blogger.com,1999:blog-3255692623413503488.post-88791134752830270232010-03-31T00:02:00.000+02:002010-09-16T12:31:54.253+02:00Gradle and IntelliJ IDEANow that I'm playing with Gradle a bit, I needed to have a way to have it play nice with my current IDE of choice, IntelliJ IDEA. At the moment IntelliJ does not support a project built by Gradle, as it does one that is built with Maven2 using a pom.xml file. But alas, using some tricks it is pretty simple.<br /><a name='more'></a><br /><br />Though IntelliJ does not support Gradle buildfiles, and vice-versa Gradle does not generate an IntelliJ project definition (yet), we can use the Eclipse integration that both provide. You can set it up in the following way. In your build.gradle file, add the <strong>eclipse</strong> plugin:<br /><pre name="code" class="java"><br />defaultTasks 'build'<br />usePlugin 'java'<br />usePlugin 'eclipse'<br /><br />repositories {<br /> mavenCentral()<br />}<br /><br />dependencies {<br /> testCompile "org.junit:junit:4.7"<br />}<br /></pre><br /><br />If you now type "gradle eclipse", gradle will generate an Eclipse <em>".project"</em> and <em>".classpath"</em> file for you. Each time you run "gradle eclipse", these two will get refreshed.<br /><br />Now go to IntelliJ IDEA. Instead of importing the project as a "new project", we choose "Open Project"<br /><img src="http://www.javadude.nl/wp-content/uploads/IntelliJ_open_project-300x102.png" alt="" title="IntelliJ Open Project" width="300" height="102" class="alignnone size-medium wp-image-22" /><br /><br />Now browse to your project, click the <em>".project"</em> file and click "open"<br /><img src="http://www.javadude.nl/wp-content/uploads/Screen-shot-2010-03-30-at-10.57.21-PM-268x300.png" alt="" title="IntelliJ Open window" width="268" height="300" class="alignnone size-medium wp-image-26" /><br /><br />Presto you're done. Now everytime gradle re-generates the classpath file, your IntelliJ project is kept in sync.Jeroen van Erphttp://www.blogger.com/profile/09896622705281991146noreply@blogger.com0tag:blogger.com,1999:blog-3255692623413503488.post-75207874219588038802010-03-25T17:02:00.000+01:002010-09-13T16:26:32.086+02:00Google Code Jam 2010 AnnouncedWill it be a new form of Alien communications, will we need to devise a new search algorithm, or something else completely...? It's that time of year again already! Google Code Jam 2010 has been announced. <a name='more'></a><br />I participated in the Google Code Jam 2009 and managed to solve a few problems. I have written about those in a post on the <a href="http://blog.xebia.com/2009/09/04/google-code-jam-2009-qualification/">Xebia blog</a>. The source code is also available in my <a href="http://github.com/hierynomus/google-code-jam">github repository</a>. In the coming weeks I'll probably add a few more exercises there and maybe update my templates a bit with some prewritten algorithms.<br /><br />Which language shall I choose? Scala worked pretty nice for some of the problems last year as they were quite functional. But I haven't written too much Scala in the past months, so I am a bit rusty.<br /><br />Anyway, the schedule can be found <a href="http://code.google.com/codejam/schedule.html">here</a> and registration will start on Wednesday, April 7.Jeroen van Erphttp://www.blogger.com/profile/09896622705281991146noreply@blogger.com0tag:blogger.com,1999:blog-3255692623413503488.post-10132494891741370472010-03-17T23:47:00.000+01:002010-09-14T10:07:27.374+02:00Custom Repository Layout in GradleFor one of the projects I work on with some colleagues, we have a number of jar files, which are not part of any Maven(-ized) repository. We decided to upload these jar files to the downloads page of github, so that we have a url which we can refer to. Using some customization in our Gradle build file, we managed to download these jars as though they were hosted on a Maven(-ized) repository.<br /><pre name="code" class="java"><br />usePlugin 'java'<br /><br />repositories {<br /> mavenCentral()<br /> add(new org.apache.ivy.plugins.resolver.URLResolver()) {<br /> name = "GitHub"<br /> addArtifactPattern 'http://github.com/asikkema/adoptimizer/downloads/[organization]-[module]-[revision].[ext]'<br /> }<br />}<br /><br />dependencies {<br /> compile "gdata:client:1.0@jar"<br /> compile "gdata:analytics:2.1@jar"<br /> compile "gdata:analytics-meta:2.1@jar"<br />}<br /></pre><br /><br />There are other options, but this was the most terse we came up with.Jeroen van Erphttp://www.blogger.com/profile/09896622705281991146noreply@blogger.com0tag:blogger.com,1999:blog-3255692623413503488.post-80145675895436211992010-03-17T23:21:00.000+01:002010-09-13T16:27:15.003+02:00Build tools introductionEver since the advent of <em>“make”</em> and its many incarnations, developers have been in search for the ultimate build tool. In the past years we have seen an ever increasing amount of build tools being developed for many different use-cases. In the coming blogs, I will take you through some of the niceties of three new build tools: Maven3, Gradle and Buildr.<br /><a name='more'></a><br />Back in the early 80s we started out with make to automatically build (parts of) a project. When Java came to power, we also started to build our Java projects with Make. However soon came Ant which was predominant for a lot of years to come. Ant buildfiles soon became a nightmare to maintain and there were no set standards between projects. Which was the task you needed to run to build the project? What were all the other non-documented tasks for? How could you set up your IDE quickly for a new project? These were questions we fought with on a semi-daily basis...<br /><br />New tools like Maven and Ivy tried to alleviate the shortcomings of the old tools with better standardization, better dependency management, etc. But how ever hard we tried, each of these tools failed in some other categories. Recently however a new wave of build tools is trying to conquer the marketplace. Maven is now close to its third incarnation, from the Ruby camp we inherited Buildr and the Groovy guys created Gradle.<br /><br />In the coming blogs I will post tips and tricks on these new tools and where possible try to compare them.Jeroen van Erphttp://www.blogger.com/profile/09896622705281991146noreply@blogger.com0