Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Problems adding Clojure to Java project

I'm working on a Java project which uses Maven to build it. The bit of functionality I'm developing would be quite cumbersome in Java, but straightforward in Clojure, so I'd like to implement it in Clojure and have Java use the resulting generated classes seamlessly.

Here's the unit test I need to pass (src/test/java/com/foo/weather/DataProcessorTest.java):

package com.foo.weather;

import static org.junit.Assert.*;
import org.junit.Test;
import java.util.*;

public class DataProcessorCljTest {
   @Test
   public void processWithTotalsAndSubTotals() throws Exception {
      assertEquals(2, DataProcessor.process(createRawData()).size());
   }

   private List<List<String>> createRawData() {
      List<List<String>> data = new ArrayList<List<String>>();
      data.add(new ArrayList<String>(Arrays.asList("2011-11-01", "Temperature", "19.2")));
      data.add(new ArrayList<String>(Arrays.asList("2011-11-01", "Pressure", "1.1")));
      return data;
   }
}

And here is the Clojure code (src/main/clojure/com/foo/weather/data-processor.clj):

(ns com.foo.weather.DataProcessor
  (:gen-class
    :methods [#^{:static true} [process [java.util.List] java.util.List]]))

(defn process [raw-data]
  (java.util.ArrayList. []))

I've added the following to my pom.xml to build the Clojure code:

<project>
   <!-- lots of stuff omitted -->
   <build>
      <plugins>
         <!-- ... -->
         <plugin>
            <groupId>com.theoryinpractise</groupId>
            <artifactId>clojure-maven-plugin</artifactId>
            <version>1.3.6</version>
            <executions>
               <execution>
                 <id>compile</id>
                 <phase>compile</phase>
                 <goals>
                   <goal>compile</goal>
                 </goals>
               </execution>
            </executions>
         </plugin>
      </plugins>
   </build>
   <repositories>
      <!-- ... -->
      <repository>
         <id>clojure-releases</id>
         <url>http://build.clojure.org/releases</url>
       </repository>
   </repositories>
   <dependencies>
      <!-- ... -->
      <dependency>
         <groupId>org.clojure</groupId>
         <artifactId>clojure</artifactId>
         <version>1.2.1</version>
       </dependency>
   </dependencies>
</project>

However, when trying to run my unit test, the compiler complains "cannot find symbol variable DataProcessor", so it seems that my Clojure code is not being compiled properly.

One thing that I've noticed is my src/main/clojure directory doesn't seem to be treated like a source directory in my IDE (IntelliJ). I right-click on src/main/clojure in the project view and choose "Mark directory as > Source root", but after reimporting Maven dependencies (i.e. "Update dependencies" in Eclipse), the directory is no longer marked as a source root.

This leads me to believe that my problem is in my Maven configuration.

Can anyone help?

like image 319
Josh Glover Avatar asked Mar 04 '12 09:03

Josh Glover


1 Answers

I use the following in my pom.xml which seems to work:

        <plugin>
            <groupId>com.theoryinpractise</groupId>
            <artifactId>clojure-maven-plugin</artifactId>
            <version>1.3.8</version>

            <executions>
                <!-- ... -->
                <execution>
                    <id>test-clojure</id>
                    <phase>test</phase>
                    <goals>
                        <goal>test</goal>
                    </goals>
                </execution>
            </executions>

            <configuration>
                <sourceDirectories>
                    <sourceDirectory>src/main/clojure</sourceDirectory>
                </sourceDirectories>
                <testSourceDirectories>
                    <testSourceDirectory>src/test/clojure</testSourceDirectory>
                </testSourceDirectories>
            </configuration>
        </plugin>

Also, I've found that Clojure works fine if you include the Clojure source files in a resource directory (you'll obviously need to load them from the Java code of course).

You might also find this question helpful: Calling clojure from java

like image 80
mikera Avatar answered Oct 20 '22 19:10

mikera