Tag Archives: Gradle

Gradle + Immutables + Eclipse

There is some documentation about IDE integration directly on Immutable web. Unfortunately none of proposed approaches works.

Fortunately there is Gradle plugin gradle-processors. Usage is deadly simple:

plugins {
  id 'org.inferred.processors' version '1.2.3'
}

dependencies {
  processor group: 'org.immutables', name: 'value', version: '2.2.6'
}

(Please not usage of processor instead of compile in dependencies)

That’s it! Just do gradle eclipse and restart Eclipse.

Gradle: Spring + FatJar = dependency on Internet connection

See my recent blog post for FatJar configuration sample. Today I found nasty behavior of Gradle plugin FatJar when used on Spring project. I hope that this post will help you not to spend whole day with it – as I did.

If your project uses only one version of each library, java packages system should assure that there will be no conflicts when merging multiple jar libraries into one big. But that does not apply to directory META-INF. This directory typically does not use packages system, so conflicts may appear.

FatJar plugin handles this situation in simple way – it just copies each file in multiple versions:

mess

That – of course – causes issues when loading. Typically only one file is picked. For example Spring stores in spring.schemas paths in resources where XSD schema files referred from your beans.xml are located in resources (so it does not need to load it from Internet). But do that for each module – Context, AOP, Web, … So only one module works.

This problem does not appear on machine with available Internet connection, because it just downloads schemas from addresses like http://www.springframework.org/schema/beans/spring-beans-3.0.xsd. But when you deploy your app on intranet server, problem appears:


143306.358000 2016-01-26 [ main] [ WARN] [factory.xml.XmlBeanDefinitionReader] [] : Ignored XML validation warning
org.xml.sax.SAXParseException: schema_reference.4: Failed to read schema document 'http://www.springframework.org/schema/beans/spring-beans-3.0.xsd', because 1) could not find the document; 2) the document could not be read; 3) the root element of the document is not <xsd:schema>.
at

....
Caused by: java.net.UnknownHostException: www.springframework.org
at java.net.AbstractPlainSocketImpl.connect(AbstractPlainSocketImpl.java:184) ~[?:1.8.0_72-internal]
at java.net.SocksSocketImpl.connect(SocksSocketImpl.java:392) ~[?:1.8.0_72-internal]
at java.net.Socket.connect(Socket.java:589) ~[?:1.8.0_72-internal]
at java.net.Socket.connect(Socket.java:538) ~[?:1.8.0_72-internal]

And then:

Exception in thread "main" org.springframework.beans.factory.xml.XmlBeanDefinitionStoreException: Line 6 in XML document from class path resource [grab_mode_beans.xml] is invalid; nested exception is org.xml.sax.SAXParseException; lineNumber: 6; columnNumber: 69; cvc-elt.1: Cannot find the declaration of element 'beans'.
at org.springframework.beans.factory.xml.XmlBeanDefinitionReader.doLoadBeanDefinitions(XmlBeanDefinitionReader.java:399)
....
Caused by: org.xml.sax.SAXParseException; lineNumber: 6; columnNumber: 69; cvc-elt.1: Cannot find the declaration of element 'beans'.
at com.sun.org.apache.xerces.internal.util.ErrorHandlerWrapper.createSAXParseException(ErrorHandlerWrapper.java:203)
at com.sun.org.apache.xerces.internal.util.ErrorHandlerWrapper.error(ErrorHandlerWrapper.java:134)

Solution is to use shadowJar. It may look like this:

buildscript {
  repositories {
    maven {
      url "https://maven.eveoh.nl/content/repositories/releases"
    }

    mavenCentral()
      jcenter()
    }

  dependencies {
    classpath 'com.github.jengelman.gradle.plugins:shadow:1.2.2'
  }
}

apply plugin: 'com.github.johnrengelman.shadow'

dependencies {
  compile project(":MyOwnProjectExample")
}

shadowJar {
archiveName "MyTest.jar";

append("META-INF/spring.schemas")
append("META-INF/spring.handlers")

manifest {
  attributes("Main-Class": "com.my.Test" )
  }
}

//this helps if you like to build fatJar as part of normal build
//otherwise use "gradle shadowJar";
assemble.dependsOn shadowJar
build.dependsOn shadowJar

I already suffered at least by 3 similar issues with following libraries:
* Spring
* Log4j2
* Lucene

I hope it helps!

Gradle + Jar (FatJar) : “Could not copy zip entry” error message

This problem is caused by https://discuss.gradle.org/t/ziptree-unable-to-overwrite-temporary-read-only-files/2322/3 resp. https://issues.gradle.org/browse/GRADLE-2959

Solution is to add delete command which removes folder ./tmp/expandedArchives:


jar {
  delete "$buildDir/tmp/expandedArchives"

  from {
    (configurations.runtime).collect {
      it.isDirectory() ? it : zipTree(it)
    }
  }

  manifest {
    attributes("Main-Class": "com.test.Main" )
    }
  }

Gradle + Eclipse plugin: Add AspectJ nature into projects

I have found nice script for adding AspectJ nature into Eclipse project using Gradle. See https://github.com/breskeby/gradleplugins/blob/0.9-upgrade/aspectjPlugin/aspectJ.gradle#L29 . Unfortunately each run of ‘gradle eclipse’ adds new nodes into project XML. Here is my fix of that issue:


eclipse.project.file.withXml { xmlProvider->
  def projectDescription = xmlProvider.asNode()
  def xmlparser = new XmlParser()

  def builders = projectDescription.buildSpec[0]

  if (!builders.buildCommand.any {it.name[0].value()=='org.eclipse.ajdt.core.ajbuilder'}) {
    def ajbuilder = xmlparser.createNode(builders, 'buildCommand', [:])
    xmlparser.createNode(ajbuilder, 'name', [:]).setValue('org.eclipse.ajdt.core.ajbuilder')
    xmlparser.createNode(ajbuilder, 'arguments', [:]);
  }

  def natures = projectDescription.natures[0]

  if (!natures.nature.any {it.value()=='org.eclipse.ajdt.ui.ajnature'}) {
    def ajnature = xmlparser.createNode(null, 'nature', [:])
    ajnature.setValue('org.eclipse.ajdt.ui.ajnature');
    natures.children().add(0, ajnature)
  }
}

Then all nodes are created only once.

Gradle + Eclipse plugin: Remove build folder from Eclipse project

By default Eclipse plugin does not add /build folder into ignored resources and that may cause /build folder to be validated. Then many warnings will appear in Markers tab of Eclipse. Beside that it may be performance problem.

I found almost suitable solution here: https://discuss.gradle.org/t/eclipse-pluging-adding-resource-filters/5408 Unfortunately it adds new filter into configuration during each ‘gradle eclipse’. Here is my fix for that situation:


eclipse.project.file.withXml { xmlProvider ->
  Node project = xmlProvider.asNode()
  Node node = project

  if (node.filteredResources.isEmpty()) {
    node = node.appendNode('filteredResources')
  } else {
    node = node.filteredResources[0]
  }

  if (!node.filter.any {it.id[0].value()[0]=='1447321705713'}) {
    Node filter = node.appendNode('filter')

    filter.appendNode('id', '1447321705713')
    filter.appendNode('name', '')
    filter.appendNode('type', 10)
    Node matcher = filter.appendNode('matcher')
    matcher.appendNode('id', 'org.eclipse.ui.ide.multiFilter')
    matcher.appendNode('arguments', '1.0-name-matches-false-false-build')
  }
}

So filter node is added only in case it does not already exists.

AspectJ and Gradle

In recent post I have described dynamical way of AspectJ waving. Today I have tried compile time way. So no JAVA_TOOL_OPTIONS is necessary.

Gradle build

See https://github.com/eveoh/gradle-aspectj for details:


buildscript {
repositories {
maven {
url "https://maven.eveoh.nl/content/repositories/releases"
}
}

dependencies {
classpath "nl.eveoh:gradle-aspectj:1.5"
}
}

project.ext {
aspectjVersion = '1.8.6'
}

apply plugin: 'java'

//eclipse support
apply plugin: 'eclipse'
apply plugin: 'eclipse-wtp'

apply plugin: 'aspectj'

Eclipse build

In Eclipse install through Help->Eclipse Marketplace plugin “AspectJ Development tools”. Then add into Gradle (adjusted version of https://github.com/breskeby/gradleplugins/blob/0.9-upgrade/aspectjPlugin/aspectJ.gradle#L29):


eclipse.project.file.withXml { xmlProvider->
def projectDescription = xmlProvider.asNode()
def xmlparser = new XmlParser()

def builders = projectDescription.buildSpec[0]
def ajbuilder = xmlparser.createNode(builders, 'buildCommand', [:])
xmlparser.createNode(ajbuilder, 'name', [:]).setValue('org.eclipse.ajdt.core.ajbuilder')
xmlparser.createNode(ajbuilder, 'arguments', [:]);

def natures = projectDescription.natures[0]
def ajnature = xmlparser.createNode(null, 'nature', [:])
ajnature.setValue('org.eclipse.ajdt.ui.ajnature');
natures.children().add(0, ajnature)
}

Then execute gradle eclipse, refresh workspace and run Project->Clean->All projects. Then start your project and waving should be already done. You can check existence of AspectJ builder in context menu of project, Properties->Builders->AspectJ Builder.