I am trying to build a Java 11 project with maven and lombok's #Slf4j Logger, but maven does not recognize the log variables. IntelliJ does though and is able to build the project.
The error is
[ERROR]: cannot find symbol variable log
Project and Module SDK is both Java 11. Lombok Version is 1.18.2:
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.12</version>
<scope>provided</scope>
</dependency>
My maven compiler setup:
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.1</version>
<configuration>
<source>11</source>
<target>11</target>
<forceJavacCompilerUse>true</forceJavacCompilerUse>
<annotationProcessorPaths>
<path>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.12</version>
</path>
</annotationProcessorPaths>
</configuration>
</plugin>
</plugins>
</build>
I already tried:
turning Annotaion Processing off and on again
reinstalling Lombok plugin
clearing .m2/repository folder
manually adding lombok.jar as Annotation Processor
adding Lombok path to maven-compiler-plugin list of Annotation Processor
This is a really minimal example configuration for using the #Slf4j lombok logging annotation.
You need a logging facade and an implementation, in this case I'm going to use slf4j (as facade) and logback (as implementation).
pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.example</groupId>
<artifactId>untitled</artifactId>
<version>1.0-SNAPSHOT</version>
<properties>
<maven.compiler.source>11</maven.compiler.source>
<maven.compiler.target>11</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.12</version>
<scope>provided</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.7.30</version>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>1.2.3</version>
</dependency>
</dependencies>
</project>
main.java
import lombok.extern.slf4j.Slf4j;
#Slf4j
public class Main {
public static void main(String[] args) {
log.debug("Hello");
}
}
If you get some trouble try always to force the maven dependencies updates running in your project folder mvn -U clean package and reimporting maven project in your IDE
My suspicion is that this is a misleading error message as a consequence of the point that Lombok hooks in during compilation.
In bytecode, there is no concept of an import. Classes are replaced by their fully qualified names (e.g. Integer to java.lang.Integer). Therefore at some point in compilation, the imports are parsed, applied, and any unknown classes (e.g. due to lack of the correct dependency) will throw an error at this stage.
Since #Slf4j means you do not need to import org.slf4j.Logger, the step described above is missed for this class.
After Lombok has appended the log field, the compiler must subsequently look at it's usage, see the class org.slf4j.Logger which it does not recognise and throws an error. Under normal circumstances, due to the earlier compilation stage, the only possible cause is that the field doesn't exist, so infers that the symbol log must be missing. What it is really failing to understand is the type of the field log.
Because Lombok makes changes in the middle of compilation, I guess spurious errors such as these are always a possibility. Perhaps Lombok developers could fix it by doing their own check for org.slf4j.Logger. Most of the functionality provided by Lombok does not involve "importing" external classes, so I'm not surprised that it doesn't handle this edge case as elegantly as possible.
If you add the dependency for SLF4J, the compiler will no longer complain.
In lombok.config file for lombok.log.custom.declaration property use full name including the package for the classes
lombok.log.custom.declaration=com.mycomp.logging.Log
com.mycomp.logging.LogFactory.getLog(TYPE)(TOPIC)
Related
I am trying to handle all cross cutting concerns e.g exception, authorization etc. in a project/repo and inject in more than one separate and independent spring-webflux project i.e handling cross-cutting concerns by building a reusable microservice platform.
Can anyone suggest how to accomplish this?
For example:- light4j handle all cross cutting concerns as middleware just need to add as plugin. But it's not compatible with SpringWebflux.
Even using AspectJ we can't use same handlers for different projects until or unless they are under same parent project.
I tried to use load-time weaving feature of AspectJ. I defined aspects in different project and add a plugin of that in current project (in which I want to use) but when exception occurred aspectJ part isn't invoked
Below is my pom.xml for current project
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.5.1</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.dummy</groupId>
<artifactId>dummydmanagement</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>DummyManagement</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-webflux</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>javax.persistence</groupId>
<artifactId>javax.persistence-api</artifactId>
<version>2.2</version>
</dependency>
<dependency>
<groupId>io.projectreactor</groupId>
<artifactId>reactor-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-validator</artifactId>
<version>5.2.4.Final</version>
</dependency>
<dependency>
<groupId>com.jaway.blog.aspectj</groupId>
<artifactId>annotations-element-value-pair-without-main-class</artifactId>
<version>1.0-SNAPSHOT</version>
<scope>system</scope>
<systemPath>/home/mmt8281/codebase/annotations-element-value-pair-without-main-class/target/annotations-element-value-pair-without-main-class-1.0-SNAPSHOT.jar</systemPath>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<excludes>
<exclude>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</exclude>
</excludes>
</configuration>
</plugin>
</plugins>
</build>
</project>
Below is pom.xml of aspect project
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.jaway.blog.aspectj</groupId>
<version>1.0-SNAPSHOT</version>
<artifactId>annotations-element-value-pair-without-main-class</artifactId>
<packaging>jar</packaging>
<dependencies>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjrt</artifactId>
<version>1.8.2</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.3</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
<encoding>UTF-8</encoding>
</configuration>
</plugin>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>aspectj-maven-plugin</artifactId>
<version>1.7</version>
<configuration>
<complianceLevel>1.8</complianceLevel>
<source>1.8</source>
<target>1.8</target>
</configuration>
<executions>
<execution>
<goals>
<goal>compile</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
Attaching gitHub links:-
AspectJ Code
DummyMgmt Code
The problem with "copy & paste programming" is that you use something you do not understand. Maybe it would be better to learn the basics first.
Having said that, there are two ways to solve your problem, given the fact that the aspect module you copied from the blog post is native AspectJ:
Configure all applications which want to use the aspect to also use native AspectJ, either by post-compile binary weaving or by load-time weaving. The Spring manual describes how to use LTW.
Trivially convert the aspect module to a Spring component and make all client projects use Spring AOP.
The latter is what I did, because I suppose that you only want to use the aspect in Spring projects and that you only annotate public methods in Spring components.
The native AspectJ solution would be more powerful, because it would also work with static and protected/private methods, even for non-Spring code and even outside of Spring completely. But why use a cannon if a pistol is sufficient?
I sent you two pull requests:
https://github.com/shas2hwat/AspectjMgmt/pull/1
https://github.com/shas2hwat/DummyManagement/pull/1
What you need to change in the aspect module, is basically this:
Remove AspectJ Maven plugin
Add org.springframework:spring-context in order to be able to add #Component to the aspect class.
I also optimised a few more things, such as update the AspectJ version.
Then, in the application module you need to:
Add org.aspectj:aspectjweaver
Add the aspect module's base package name to the component scan
I also removed the ugly system dependency with the fixed path to the aspect module. If you simply run mvn clean install on the aspect module before you build the application, the library will be found in the local Maven repository. (I think, you need to urgently learn some Maven basics.)
Now when running this application
#SpringBootApplication
#ComponentScan(basePackages = {"com.dummy.dummydmanagement", "com.jayway.blog"})
public class DummyManagementApplication {
public static void main(String[] args) throws Exception {
ConfigurableApplicationContext context = SpringApplication.run(DummyManagementApplication.class, args);
context.getBean(ItemService.class).getAllItemsService();
}
// (...)
}
the console log will be:
YourAspect's aroundAdvice's body is now executed Before yourMethodAround is called.
Exception occured
YourAspect's aroundAdvice's body is now executed After yourMethodAround is called.
Of course, annotating the static main method does not work with Spring AOP, which is why I removed the annotation. That would only work with native AspectJ. Please let me know if you need that, but I think you should keep it simple, because you clearly do not understand the tools you are using.
Update: Because for whatever reason the OP is angry with me now, because I told him to stop texting me directly on Telegram, he also deleted his own repositories. For anyone interested, here are my clones, containing both the original code and my modifications fixing the problem, as described above:
https://github.com/kriegaex/AspectjMgmt, relevant commit here
https://github.com/kriegaex/DummyManagement, relevant commit here
I am trying to integrate JavaFX inside of an SWT application using FXCanvas. For reference, I am following this oracle guide
Within my IDE this chunk of code displays an error
/* Create an FXCanvas */
final FXCanvas fxCanvas = new FXCanvas(shell, SWT.NONE) {
#Override
public Point computeSize(int wHint, int hHint, boolean changed) {
getScene().getWindow().sizeToScene();
int width = (int) getScene().getWidth();
int height = (int) getScene().getHeight();
return new Point(width, height);
}
};
Error:
(yes, I have imported the correct Point class: org.eclipse.swt.graphics.Point):
'computeSize(int, int, boolean)' in 'Anonymous class derived from javafx.embed.swt.FXCanvas' clashes with 'computeSize(int, int, boolean)' in 'javafx.embed.swt.FXCanvas'; attempting to use incompatible return type
However, I don't think this is the root cause... Because when I try to build the project (maven) I get this error:
package javafx.embed.swt does not exist. Which I believe is the true issue.
So after doing some research I have checked a few things, firstly, the jfxswt jar looks like it should be accessible:
and if I open the JAR, you can see FXCanvas is there:
I even tried adding the JAR manually as a library to my module, still doesn't work.
Here is my pom.xml, (i've intentionally anonymized certain info)
I will also mention that I have tried this in a fresh project without any maven dependencies, and just adding swt and such as libraries manually with the same error.
<?xml version="1.0" encoding="UTF-8"?>
<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId></groupId>
<artifactId></artifactId>
<version></version>
</parent>
<artifactId></artifactId>
<version>2.0.0.0-SNAPSHOT</version>
<packaging>jar</packaging>
<name></name>
<description></description>
<dependencies>
<dependency>
<groupId>pentaho-kettle</groupId>
<artifactId>kettle-engine</artifactId>
</dependency>
<dependency>
<groupId>pentaho-kettle</groupId>
<artifactId>kettle-core</artifactId>
</dependency>
<dependency>
<groupId>pentaho-kettle</groupId>
<artifactId>kettle-ui-swt</artifactId>
</dependency>
<dependency>
<groupId>org.eclipse.swt</groupId>
<artifactId>org.eclipse.swt.gtk.linux.x86_64</artifactId>
</dependency>
<dependency>
<groupId>org.eclipse</groupId>
<artifactId>jface</artifactId>
<version>3.3.0-I20070606-0010</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.4</version>
</dependency>
<!-- https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-databind -->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
</dependency>
</dependencies>
</project>
Am I missing something, any ideas?
You will need to add the jfxswt.jar file to your classpath for compile and for execution.
This can be done by using the system scope as that jar file is part of your JDK under the jre/lib directory.
<dependency>
<!-- GroupId/ArtifactId/Version doesn't matter unless it clashes. -->
<groupId>jfxswt</groupId>
<artifactId>jfxswt</artifactId>
<version>1.8</version>
<scope>system</scope>
<systemPath>${java.home}/lib/jfxswt.jar</systemPath>
</dependency>
This will instruct maven to add the jre/lib/jfxswt.jar to the classpath. This could cause an issue if someone uses different JDK what has that jar in other places but for Java 8 you should be okay.
You have to add the jfxswt.jar to your classpath when you execute your application.
In maven you can use the exec plugin:
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<version>3.0.0</version>
<executions>
<execution>
<goals>
<goal>java</goal>
</goals>
</execution>
</executions>
<configuration>
<mainClass>twobuttons.TwoButtons</mainClass>
<additionalClasspathElements>
<!-- The run environment must configure the system jar. -->
<element>${java.home}/lib/jfxswt.jar</element>
</additionalClasspathElements>
</configuration>
</plugin>
Notes:
The system scope is deprecated in maven in favor of installing files to repositories. The solution above works fine at the moment.
The content of the jfxswt.jar can be part of some SWT libraries unfortunately I am not familiar with SWT. If you can find that jar in a Maven repo than just include that instead of messing with the system scope.
The twobuttons.TwoButtons class is from the tutorial you mentioned.
I am new to Dagger 2 and am trying out the Dagger 2 Coffee Example in IntelliJ and it seems that is does not generate a DaggerCoffeeApp_Coffee (It should be generating it) even though I followed the code example for Dagger 2 in github closely.
Public class CoffeeApp {
#Singleton
#Component(modules = {DripCoffeeModule.class})
public interface Coffee {
CoffeeMaker maker();
}
public static void main(String args[]){
Coffee coffee = DaggerCoffeeApp_Coffee.builder().build();
}
}
Here is my pom.xml file.
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.tim.test</groupId>
<artifactId>Dagger2Experiment</artifactId>
<version>1.0-SNAPSHOT</version>
<properties>
<slf4j-api.version>1.7.12</slf4j-api.version>
</properties>
<repositories>
<repository>
<id>sonatype</id>
<name>sonatype-repo</name>
<url>https://oss.sonatype.org/content/repositories/snapshots/</url>
</repository>
</repositories>
<dependencies>
<dependency>
<groupId>com.google.dagger</groupId>
<artifactId>dagger</artifactId>
<version>2.0.1</version>
</dependency>
<dependency>
<groupId>com.google.dagger</groupId>
<artifactId>dagger-compiler</artifactId>
<version>2.0.1</version>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>${slf4j-api.version}</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>${slf4j-api.version}</version>
<scope>runtime</scope>
</dependency>
</dependencies>
</project>
I have tried various solution from the topic below but nothing seems to work:
I have also added jar file to my application buildpath dagger-2.0.1.jar in your application's runtime and dagger-compiler-2.0.1.jar in your build at compile time.
Update
I used DaggerCoffeeApp_Coffee.builder().build() in the code snippet above since I edited my code to follow the code example in Dagger 2's github below after I couldn't find the constructor. Link below:
https://github.com/google/dagger/blob/master/examples/simple/src/main/java/coffee/CoffeeApp.java
Any help will be greatly appreciated.
Update
Yep, You caught me skimming the question. I failed to read your code example otherwise I would have seen the pom.xml wasn't the only issue.
I'm assuming your DripCoffeeModule is annotated correctly and has no parameters in its constructor so that you don't need to specify this in building the Component. E.g. :
#Module
public DripCoffeeModule {
//Uses default constructor
}
I've not seen the Component implemented as an inner class before but I'm betting that Dagger won't treat this any different in terms of instantiating. (I would recommend moving it out of CoffeeApp class.) The naming, however, would be incorrect. Instead of
DaggerCoffeeApp_Coffee.builder().build();
You have to follow the naming convention defined by Dagger. From the section titled Building the Graph on Dagger's website:
The implementation has the same name as the interface prefixed with Dagger.
So you need to modify the line to:
DaggerCoffee.builder().build();
or you can use the convenience method:
DaggerCoffee.create();
If I'm wrong about number 1, then you will need to construct your Module as well like so:
DaggerCoffee.builder().dripCoffeeModule(new DripCoffeeModule()).build();
Original
Move the compiler from the dependencies section into the compiler section. From the Dagger 2 official site.
In a Maven project, one would include the runtime in the dependencies section of your pom.xml, and the dagger-compiler artifact as a dependency of the compiler plugin:
For example:
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<dependencies>
<dependency>
<groupId>com.google.dagger</groupId>
<artifactId>dagger-compiler</artifactId>
<version>2.0</version>
<optional>true</optional>
</dependency>
</dependencies>
</plugin>
I chased a similar problem then realized I was not importing the #Component interface generated implementation. Once I added the import, using the same package path as my interface, my code compiled and worked.
There is something I don't understand with maven and I didn't find any answer out there. So I ask it here, hoping to get an answer.
I added a jar as a maven dependency for a project as system scope.
When I run analyze-only goal on dependency plugin, it does find it. But whenever I want to use classes located in default package in this jar, it won't compile.
I did the same with a jar from same provider with same classes but this time located in one package other than default and it compiles.
Is there something obvious I missed or has someone already encountered the same problem ?
It is not worth posting the code as I just try to import one of the class of system dependency.
My POM (system dependency)
<?xml version="1.0" encoding="UTF-8"?>
<project>
<modelVersion>4.0.0</modelVersion>
<groupId>edu.algo</groupId>
<artifactId>algorithms</artifactId>
<version>1.0</version>
<properties>
<lib.path>C:/lib</lib.path>
</properties>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.8.1</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>edu.princeton.cs</groupId>
<artifactId>stdlib</artifactId>
<version>1.0</version>
<scope>system</scope>
<systemPath>${lib.path}/stdlib/stdlib.jar</systemPath>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<version>2.6</version>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>2.5.1</version>
<configuration>
<source>1.7</source>
<target>1.7</target>
</configuration>
</plugin>
</plugins>
</build>
</project>
Sorry to bother you guys and thanks for your help.
I found the answer to my question and it has nothing to do with maven. You just cannot import classes in default package from named package for java versions above 1.4, I was using 1.7 version for compilation.
http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4989710
Have you supplied the JAR it's looking for? It sounds like it can't find the JAR against which to compile against.
Have you read this?
http://docs.codehaus.org/display/MAVENUSER/Dependency+Scopes
It states:
system: This dependency is required in some phase of your project's
lifecycle, but is system-specific. Use of this scope is discouraged:
This is considered an "advanced" kind of feature and should only be
used when you truly understand all the ramifications of its use, which
can be extremely hard if not actually impossible to quantify. This
scope by definition renders your build non-portable. It may be
necessarry in certain edge cases. The system scope includes the
element which points to the physical location of this
dependency on the local machine. It is thus used to refer to some
artifact expected to be present on the given local machine an not in a
repository; and whose path may vary machine-to-machine. The systemPath
element can refer to environment variables in its path: ${JAVA_HOME}
for instance.
So, unless you have a solid reason for using this, maybe it's better to deploy the artifact into the repository and reference it like any other artifact?
I would like to use the Fluido skin for my Maven-based project.
If I add it only in src/site/site.xml the mvn site fails because the artifact is missing. It ask to manually install the artifact, but I would like to avoid that step for my colleagues.
I've added the following dependency to my pom.xml:
<dependency>
<groupId>org.apache.maven.skins</groupId>
<artifactId>maven-fluido-skin</artifactId>
<version>1.2.2</version>
</dependency>
And it seems to work: the skin is automatically downloaded by maven when I do mvn site. However I do not want that my project be marked as a dependency of that artifact ; I don't want that package to be in the classpath during compile, test, etc.
I don't see any dependency scope that would restrict the dependency just for site:site.
Did I miss something about dependency scope? Is using dependency for that relationship the right thing?
I do not have time to try this myself, but I think the following should work:
<project>
...
<build>
<plugins>
...
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-site-plugin</artifactId>
<dependencies>
<dependency>
<groupId>org.apache.maven.skins</groupId>
<artifactId>maven-fluido-skin</artifactId>
<version>1.2.2</version>
</dependency>
</dependencies>
</plugin>
</plugins>
</build>
...
</project>