Maven + MWE2Launcher + XText model refences an uncompiled Java Class - java

i have a Question about XText/Maven.
I have a XText/Maven/Java Project.
In this Project lie the Xtext Models and Java source Files.
Some of the Modelfiles reference some Java files. E.G.:
Model:
package a.b.c
import java.util.List
import x.y.z.MyClass // <-- This is one of the Javafile in the same Project
dto MyModel
{
MyClass myClass
}
Java:
package x.y.z;
public class MyClass
{
String foo;
String bar;
}
Structure:
project
|
|----src/main
|
|---/java/x/y/z/MyClass.java
|
|---/model/a/b/c/MyModel.dto
|
|---/gen/a/b/c/MyModel.java <-- here goes the generated Javafile from the Model
I have already managed to write an Xtext/Eclipse plugin, so the Eclipse build generate my Modelfiles and compiles the Javafiles just fine.
But now i try to build the Project with Maven. I Manage already accomplished the Generate process via an mwe2 Workflow with use of the Class
org.eclipse.emf.mwe2.launch.runtime.MWE2Launcher
and other Modelfiles genrate just fine, but the MyModel references a Java Class that is not yet Compiled and so it is not Found:
[ERROR] Execution Failed: Problems running workflow my.company.model.xtext.domainmodel.generator: Validation problems:
[ERROR] 49 errors:
[ERROR] MyModel.dto - <path>/model/a/b/c/MyModel.dto
[ERROR] 4: x.y.z.MyClass cannot be resolved to a type.
...
So the Error itself is clear. I tryed with sucess to Precompile the Java File first and add these to the Classpath. But i have dozen of this Problems and i hope the is a better way to tell Xtext/Mwe2Launcher that it should reference the requierd Java Files. Because in some magic way it already work in Eclipse but i have no Idea how.

I have the same problem. But I use Gradle instead of Maven. However it may be still useful for someone:
task precompile(type: JavaCompile) {
source = 'src/main/java'
classpath = sourceSets.main.compileClasspath
destinationDir = sourceSets.main.java.outputDir
}
task generateXtextLanguage(type: JavaExec) {
dependsOn precompile
main = 'org.eclipse.emf.mwe2.launch.runtime.Mwe2Launcher'
args += "src/main/mwe2/...your_path_here.../generate.mwe2"
classpath = layout.files(configurations.mwe2, sourceSets.main.java.outputDir)
inputs.file 'src/main/mwe2/...your_path_here.../generate.mwe2'
inputs.dir 'src/main/xcore'
outputs.dir 'target/generated-sources/xtext-gen'
}
I added precompile task. generateXtextLanguage dependsOn it. Also I added precompiled classes to a classpath.

Related

Working on a legacy java program using NetBeans, I am unable to import the junit.framework.TestCase the original author used in Test.java files

To start things off, I am entirely new to Java. I'm a C#/Powershell guy. A client at my IT Firm had an issue with a java program that they were executing on a daily basis that was having issues. According to Windows, the original program was written in April of 2011. I was able to unzip the file and pulled out all of the java files. I then rebuilt the program's structure in NetBeans and am getting ready to start editing. However, each *Test.java file is unable to import junit.framework.TestCase. In the original program file, each of these files were in the same folders as their associated files. From what I can tell, that is not best practices but it was the folder structure I found in the *.jar file I pulled them from. i.e.:
+ Source Packages
|
+--+ Folder
|
+--Example.java
|
+--ExampleTest.java
This leads me to 2 potential issues:
Reading similar threads regarding junit.framework "does not exist", there is mention of adding the junit.jar to the POM or adding the dependency to maven. For NetBeans, how do I do this? Using the "Add Dependency" menu, I am unable to find a "junit.framework" and there is 125,000 results for junit that I am unsure which one I need. Any insights? At the time of the original program's writing, v3 and v4 were both released, although v3.8.1 remained in use for some time beyond the adoption of v4.
For its use-case, see below. I assume all the errors are related to the junit import, so I included them as comments.
package com.example.program;
import java.util.Properties;
import junit.framework.TestCase;
/* Import files specific to program */
public class ExampleTest extends TestCase { //Cannot find symbol (class) "TestCase"
private Properties config = null;
#Override //Error: method does not override or implement a method from a supertype
/* SetUp function/method w/out any issues, creates config Properties object */
public void testExample(){
String line = "*"; // some csv line being parsed
CSVLine csvLine = new CSVLine(line, config);
assertEquals(/* does stuff */); // Error: cannot find "symbol" (method) "assertEquals"
assertTrue(/* does stuff */); // Error: cannot find "symbol" (method) "assertTrue"
assertTrue(/* does stuff*/); // Error: cannot find "symbol" (method) "assertTrue"
}
}
Do I need to move these Test.java files into a folder under the Test Packages section of the POM? Why would the original program have them in the same directory as their counterparts? Does some aspect of compiling/building move them to the same location?

Gradle can not compile the code with the generated sources by annotationProcessor

How to make the gradle build/compile a project using generated source by annotationProcessor?
I have a project with 2 modules
app-annotation -> is a module that defines one annotation and a successor of the AbstractProcessor
app-api -> contains Entities with annotation from the previous module
The idea was to generate default CRUD Repositories and Services for each entity, also if it is needed have the possibility to extend some service.
The problem is, it generates all the needed java files (even Intellij Idea see those files) but as soon as I want to extend one of the services it fails while it is being compiled because as I understand at the moment of compiling my class there is not its superclass which is generated after.
If I do then recompile only my class then it is ok
Moreover, eclipse somehow compiles with no error at all, only when I build with Idea or gradlew build.
To fix it the solution below is used, but it looks not very nice
configurations {
preProcessAnnotation
}
def defaultSrcDir = "$projectDir/src/main/java"
def entitySources = "$projectDir/src/main/java/com/abcd/app/entity"
def generatedSources = "$buildDir/generated/sources/annotationProcessor/java/main"
def generatedOutputDir = file("$generatedSources")
// Explicitly run the annotation processor against the entities
task preProcessAnnotation (type: JavaCompile) {
source = entitySources
classpath = sourceSets.main.compileClasspath
destinationDirectory = generatedOutputDir
options.sourcepath = sourceSets.main.java.getSourceDirectories()
options.annotationProcessorPath = configurations.getByName("preProcessAnnotation")
options.compilerArgs << "-proc:only"
options.encoding = "ISO-8859-1"
}
// Explicitly specify the files to compile
compileJava {
dependsOn(clean)
dependsOn(preProcessAnnotation)
def files = []
fileTree(defaultSrcDir).visit { FileVisitDetails details ->
files << details.file.path
}
fileTree(generatedSources).visit { FileVisitDetails details ->
files << details.file.path
}
source = files
options.compilerArgs << "-Xlint:deprecation"
options.compilerArgs << "-Xlint:unchecked"
options.encoding = "ISO-8859-1"
}
....
dependencies {
preProcessAnnotation project(':app-annotation')
// Generate the crud repositories and services
compile project(':app-annotation')
implementation project(':app-annotation')
...
}
I am just curious how similar frameworks of code generation such as Lombok, Dagger2 work without any problem.
PS. I feel it should be much simpler, doesn't it?
Eventually, all it is my mistake, I used wrong method to save a generated java file.
// Wrong!
javax.annotation.processing.Filer#createResource(StandardLocation.SOURCE_OUTPUT, packageName, className + ".java")
// Correct
javax.annotation.processing.Filer#createSourceFile(packageName + "." + className)
As you realised - any code generation must be done before compile.
A cleaner approach is to have your code generation logic / annotation as dependency.
task codeGen {
// creates under build/genSrc
}
//add to default source set
sourceSets.main.java.srcDir "build/genSrc"
//this has access to all code
compile.dependsOn codeGen

Gradle: get a Groovy test script to use an auxiliary Java class

I'm trying to work out how I get a Groovy test script to import a Java class during the testing phase ...
Specifically I want to use JavaFXThreadingRule: .java file from here (or rather here and so included in my Java test source path) and then import it in my Groovy test script to use as an annotation.
The Groovy test script path is src\test\ft\groovy\core\testscript.groovy.
The .java file is src\test\ft\java\core\JavaFXThreadingRule.java.
The package line I've used in both is "package core;"
My "sourceSets" clause in build.gradle looks like this:
sourceSets {
main {
java {
srcDirs = ['src/main/java']
}
}
test {
java {
srcDirs = ['src/test/ft/java' ]
}
groovy {
srcDirs = ['src/test/ft/groovy', 'src/test/ut/groovy']
}
}
}
Interestingly the build.gradle output shows that the compileTestJava task is run before the compileTestGroovy task ... and yet I get
unable to resolve class core.JavaFXThreadingRule # line 18, column 1.
import core.JavaFXThreadingRule ^
NB I also tried "import JavaFXThreadingRule" - same result.
In addition to just wanting to resolve the problem I'm also wondering how Gradle decides what order to do the tasks compileTestJava and compileTestGroovy... and whether I shouldn't perhaps make my compileTestGroovy explicitly dependent on compileTestJava...
Thanks to Tim Yates I found the "workaround" of putting this Java file in with the Groovy ones... but this answer gave me another clue, and I then changed my build.gradle to be like this:
sourceSets {
main {
java {
srcDirs = ['src/main/java']
}
}
test {
groovy {
srcDirs = ['src/test/ft/groovy', 'src/test/ut/groovy', 'src/test/ft/java' ]
}
}
}
... works ... no doubt obvious to old Gradle hands.
That question and answer referenced above were talking about the app code classes (and Gradle tasks). Unless some Gradle expert can say otherwise I'm assuming that the Groovy test compile task and Java test compile task are completely separate and can't "see" one another's classes...

How to access version of my project in build.gradle from a Java class

I'm quite new to Gradle so the answer might be simple, so I apologize if the answer is simple: I have a testing tool that needs to fetch it's version and compare it to the version of the application it is testing. However , the version of my tool is in my build.graddle as
version '1.0'
I tried different way to access it ( such as) :
task generateSources {
File outDir
outDir = file("$buildDir/classes/test/tests/Version.java")
doFirst {
outDir.exists() || outDir.mkdirs()
new File(outDir).write("public class Version { public static final String VERSION = \"$project.version\"; }")
}
}
compileJava.dependsOn generateSources
compileJava.source generateSources.outputs.files, sourceSets.main.java
I found this piece of code to output the version to another java file, but I fail to see how I'd be able to retrieve that info afterwards ( I mean, my tests are defined in src and I would need to point to a file that doesn't exist at compilation -- correct me if I'm wrong here).
Any idea on how I could accomplish this task?
First of all, you are trying to create java source file in your build/classes (it should contain compiled classes, not sources) directory, but you have to do it in your sources, otherwise it won't be compiled. And if you need this new class to be vailable not for tests, then use src/main/java, not src/test/java/
But anyway, I suppose for your case it's much easier to use some properties file for that and replace some token within it during build. That will allow you to make some static logic to get this property value and use it yet before running the build. So all you need is:
1- to have some properties file in your resources src/main/resources (for example app.properties), where should version variable be stored, with it's value like APP_VERSION_TOKEN
version=%APP_VERSION_TOKEN%
2- configure you Gradle processResources to replace tokens, something like this:
processResources {
filesMatching('**/app.properties') {
filter {
it.replace('%APP_VERSION_TOKEN%', version)
}
}
}
3- make some method to read this file and return the value of the property and use it where you need.
And that's all. For unit tests you can have another file with the same name under src/test/resource with the unchanging value you need for testing.

gradle generated files fail to compile

I am trying to get a JavaCC plugin working properly with Gradle. The plugin generates .java files correctly, but then during the compileJavaC task it crashes and burns with cannot find symbol errors. My JavaCC .jj file contains code that references other java files that are not generated, and I am guessing that the compileJava task tries to compile the generated code without providing a reference to the non-generated code.
Here is a minimum breaking example. build.gradle:
apply plugin: 'java'
//compile .jj file in src/main/javacc
buildscript {
repositories {
mavenCentral()
}
dependencies {
classpath group: 'ca.coglinc', name: 'javacc-gradle-plugin', version: '1.0.0'
}
}
apply plugin: 'javacc'
src/main/MyClass.java:
public class MyClass {
public MyClass(){
}
}
and src/main/javacc/MyParser.jj:
options
{}
PARSER_BEGIN(MyParser)
import java.util.*;
public class MyParser {
public static void main(String[] args) throws ParseException {
MyClass mc = new MyClass();
}
}
PARSER_END(MyParser)
SKIP:
{
" "
}
TOKEN:
{
<ANYTHING: ~[]>
}
void production():
{}
{
(<ANYTHING>)+
}
Running gradle build gives the following:
gradle build
:compileJavacc
Java Compiler Compiler Version 5.0 (Parser Generator)
(type "javacc" with no arguments for help)
Reading from file C:\Users\Nate Glenn\Desktop\java_workspace\test-gradle-javacc\
src\main\javacc\MyParser.jj . . .
File "TokenMgrError.java" does not exist. Will create one.
File "ParseException.java" does not exist. Will create one.
File "Token.java" does not exist. Will create one.
File "SimpleCharStream.java" does not exist. Will create one.
Parser generated successfully.
:compileJavaC:\Users\Nate Glenn\Desktop\java_workspace\test-gradle-javacc\build\
generated\javacc\MyParser.java:5: error: cannot find symbol
MyClass mc = new MyClass();
^
symbol: class MyClass
location: class MyParser
C:\Users\Nate Glenn\Desktop\java_workspace\test-gradle-javacc\build\generated\ja
vacc\MyParser.java:5: error: cannot find symbol
MyClass mc = new MyClass();
^
symbol: class MyClass
location: class MyParser
2 errors
FAILED
FAILURE: Build failed with an exception.
* What went wrong:
Execution failed for task ':compileJava'.
> Compilation failed; see the compiler error output for details.
* Try:
Run with --stacktrace option to get the stack trace. Run with --info or --debug
option to get more log output.
BUILD FAILED
Total time: 9.002 secs
How can I fix my Gradle build file so that javaCompileC correctly includes non-generated files when compiling the generated files?
Your source tree for MyClass is incorrect. It should be src/main/java/MyClass.java. In gradle, just like maven, convention is that java files by default are in src/main/java, and since you're not overriding this in your build.gradle file, I assume this is just an error on your part. The plugin correctly adds the JavaCC output path to the compileJava task's classpath, so if you create your java classes in the correct path for the compileJava task, everything should be fine :)
Just tried your example this way and it works.
By the way, thanks for your contribution to the plugin.
Just some additional FYI, if you would like to overwrite the compile path, here is how you would do it:
//customized source sets to over-write the default src/main/java path
sourceSets {
main{
java {
srcDir 'Java Source'
}
resources {
srcDir 'resources'
}
}
test {
java {
srcDir 'tests'
}
}
}

Categories

Resources