I had a Java 8 project and my configuration file was in resource folder and everything worked fine. Now I switched to Java 9, added requirement for log4j.api, and configuration file cannot be found anymore.
Do I need to add something else in my module-info file for the logger to find it's config?
For now, it's like this
module project.main {
requires jdk.incubator.httpclient;
requires jackson.databind;
requires jackson.core;
requires jackson.annotations;
requires log4j.api;
}
The Project structure is as:
The build.gradle file is as:
The log4j~faq suggests using at least log4j-api-2.x and log4j-core-2.x. Preferably add these to your build.gradle file:
compile group: 'org.apache.logging.log4j', name: 'log4j-core', version: '2.9.0'
compile group: 'org.apache.logging.log4j', name: 'log4j-slf4j-impl', version: '2.9.0'
compile group: 'org.apache.logging.log4j', name: 'log4j-1.2-api', version: '2.9.0'
And make sure conflicting dependencies are excluded
In the module-info.java further you shall update(this is what I did in a custom maven project)
requires log4j; // not log4j.api
It should work for you then with the same directory structure as well.
Hint: This is where I started debugging it from.
Why do I see a warning about "No appenders found for logger" and "Please configure log4j properly"?
This occurs when the default configuration files log4j.properties and
log4j.xml can not be found and the application performs no explicit
configuration. log4j uses Thread.getContextClassLoader().getResource()
to locate the default configuration files and does not directly check
the file system...
Placed a debug point in the ClassLoader#getResource method and just keep an eye of resources looked for by the library.
Also to bring up the point over resources like resources/foo/bar/log4j.properties as stated in the release notes in JDK-8142968
JDK internal resources, other than class files, in the standard and JDK modules can no longer be located with the
ClassLoader.getResourceXXXAPIs. This may impact code that relies on
using these APIs to get at JDK internal properties files or other
resources.
and seconded by the java-doc of ClassLoader#getResource as well:
Resources in named modules are subject to the encapsulation rules
specified by Module.getResourceAsStream. Additionally, and except for
the special case where the resource has a name ending with ".class",
this method will only find resources in packages of named modules when
the package is opened unconditionally (even if the caller of this
method is in the same module as the resource).
Related
I'm getting this error while trying to commit my changes into gitlab repo and deploy it in kubernetes after upgrading gradle version to 7.4
Also I think the problem in how I include my shared library inside the project it self, that's what I sense from the error output below
Could not determine the dependencies of task ':distTar'.
Could not resolve all task dependencies for configuration ':runtimeClasspath'.
Could not resolve project :vlc-shc.
Required by:
project :
> No matching configuration of project :vlc-shc was found. The consumer was configured to find a runtime of a library compatible with Java 11, packaged as a jar, preferably optimized for standard JVMs, and its dependencies declared externally but:
- None of the consumable configurations have attributes.
build.gradle:
dependencies {
implementation project(':vlc-shc')
}
setting.gradle:
rootProject.name = 'vlc-myProject'
include ('vlc-shc')
I added this artifact which is a war to my gradle project dependencies.
I need to extend some classes, and use a modified servlet contexts from it.
I was expecting the war to be imported as is then I would use gradle tasks to manipulate to include the jars to dependencies, copy static resources to correct classpath etc.
But gradle actually added a bunch of jars to dependency.
Im not sure if gradle scanned recursively all paths for jars and poms or probably just the jars under the WEB-INF/classes folder in the war.
I can assume probably not the poms repositories as stated here.
Im I correct is assuming the jars in the WEB-INF/lib folder in the deflated war were not imported? its hard to tell as there are a lot of shared dependencies between my project and the war in question
Then whats the best way to declare a dependency on a war in the maven repo/jcenter if I need to extend and modify as I described at the top?
UPDATE:
I am now trying to use answer below and this solution https://discuss.gradle.org/t/how-to-add-an-artifactory-war-as-a-gradle-dependency/19804/2
, This only worked after moving the directory with the copied jars outside the buildDir
my build.gradle
configurations {
warOnly
}
dependencies {
// not working implementation fileTree('$buildDir/explodedWar/WEB-INF/classes')
implementation fileTree('anotherDir/explodedWar/WEB-INF/classes')
// implementation fileTree('$buildDir/explodedWar/WEB-INF/lib')
implementation fileTree('anotherDir/explodedWar/WEB-INF/lib')
warOnly 'ca.uhn.hapi.fhir:hapi-fhir-jpaserver-starter:4.2.0#war'
}
tasks.register("explodeWar",Copy) {
from zipTree(configurations.warOnly.singleFile)
// into "${buildDir}/explodedWar"
into "anotherDir/explodedWar"
}
compileJava {
dependsOn explodeWar
}
By declaring a dependency on a WAR, Gradle will simply add it to the list of files for the matching configuration. So if you add a WAR in implementation, it will simply be on the compileClasspath and runtimeClasspath without any processing.
So for sure Gradle will not transform your WAR dependency in a dependency on the JARs it contains.
If you want to use a WAR to copy and modify some of its content before repackaging it, you can use an isolated and custom configuration to resolve it from a remote repositories. Then you will define a Gradle task that will take the files of that configuration as the input and do the required processing on the WAR. Note that the task could also be the starting point of a series of tasks manipulating the WAR to one output, then that output to another one, etc ...
configurations {
warOnly
}
dependencies {
warOnly "com.pany:some-war:1.0"
}
tasks.register("copyWar", Copy) { // Register a copy task to modify the WAR
from(zipTree(configurations.warOnly)) // I did not run this, so you may have to get to the single file instead
// Regular copy configuration to decide a destination, perform on the fly changes, etc ...
}
It took some trail and error but there is better way. When using the dependency:
providedCompile 'ca.uhn.hapi.fhir:hapi-fhir-testpage-overlay:6.0.1'
Gradle will download a war file and place it you your classpath. However providing a classifier will help here. The following dependency will get the jar file.
providedCompile (group: 'ca.uhn.hapi.fhir', name: 'hapi-fhir-testpage-overlay', version:'6.0.1', classifier: 'classes')
I am building a library, which has separate entry points (like server, gui), with different dependencies. Each entry point is in a separate sub project with its own dependencies.
In the root project, where I start the build from, I want to select the entry point, and only build with that dependencies. That is working.
But I want to instantiate a class (eg MainClass) of the root project from the library entry point and I cant add the root projects class path to the dependency. (Diagram)
Root projects build file looks like this now:
dependencies{
implementation project(':server')
}
It seems to me that it would be easier to understand and clearer if the entry point projects depended on the core API instead of vice versa.
You could have project structure like:
settings.gradle
core/
build.gradle
src/
server/
build.gradle
src/
gui
build.gradle
src/
server and gui project build.gradle files should contain:
dependencies {
implementation project(':core')
}
The project that uses the library could depend on Server and/or GUI projects and instantiate the necessary class (ServerEntry or GuiEntry) directly.
If you want to be able to switch between different entry point implementations without changing the code in the project that uses the entry point instance I'd suggest using a dependency injection framework (Spring, Guice, Dagger). Dependency injection would help to separate configuration (binding interfaces to classes) from the actual application.
I solved my problem with Composite build. I added includeBuild '../path-to-lib' in the settings.gradle, Than I created a subproject Project to the library with the proper package and class name. On run it throws an error, that the developer should create this class.
Its also important to add all the subprojects to the same group:
allprojects{
group = 'library-group'
}
In the host project, I can depend on the library:
dependencies{
implementation module('library-group:suproject')
}
Now Gradle automatically overwrites the Classes on the same route as the documentation suggest, and I can finally inject my host project into the lib, and compile it as a whole.
I am attempting to create a program in Java using Netbeans. I am attempting to use org.slf4j. I think I have placed the sufficient amount of slf4j jar files in my CLASS PATH. I have placed slf4j-api, slf4j-jcl, slf4j-jdk14, slf4j-nop and slf4j-simple in my class path.
My question is: Am i placing the wrong jar files in my class path, the Zip file for the slf4j folder included a large amount of jar files. Why are there so many executable jar files included for SLF4J.
Ultimately, the program needs to compare 2 pdf files at a time and spit out an error message if the files are different. Would anyone know if there is anything out there that I can include so I don't have to deal with this SLF4J package.
Below is where I am attempting to run the package.
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
Set Dependencies as follows.
In Maven
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>version number</version>
</dependency>
In Gradle
dependencies {
compile group: 'org.slf4j', name: 'slf4j-api', version: 'version number'
}
In Gradle add the following dependencies:
implementation 'org.slf4j:slf4j-api:1.7.28'
implementation 'org.slf4j:slf4j-simple:1.7.28'
The last one dependency needs to be added to Resolve "Failed to load class org.slf4j.impl.StaticLoggerBinder"
In build.gladle ( the second one ) look at dependencies and add this line:
dependencies {
...
implementation 'org.apache.directory.studio:org.slf4j.api:1.7.2'
}
I'm trying to implement a jsr 356 websocket connection from within a war deployed in jetty.
I'm using this as a guide: http://aredko.blogspot.com/2013/11/java-websockets-jsr-356-on-jetty-91.html
(I can find lots of tutorials on basically using jsr 356 with an embedded jetty server, but none on building a websocket connection within an existing server - are there any good ones out there?)
Whenever I run the code listed above, I get the following error:
java.lang.LinkageError: loader constraint violation: when resolving method "org.eclipse.jetty.websocket.jsr356.server.deploy.WebSocketServerContainerInitializer.configureContext(Lorg/eclipse/jetty/servlet/ServletContextHandler;)Lorg/eclipse/jetty/websocket/jsr356/server/ServerContainer;" the class loader (instance of org/eclipse/jetty/webapp/WebAppClassLoader) of the current class, com/me/stuff/data/DataServer, and the class loader (instance of org/eclipse/jetty/start/Classpath$Loader) for resolved class, org/eclipse/jetty/websocket/jsr356/server/deploy/WebSocketServerContainerInitializer, have different Class objects for the type y.websocket.jsr356.server.deploy.WebSocketServerContainerInitializer.configureContext(Lorg/eclipse/jetty/servlet/ServletContextHandler;)Lorg/eclipse/jetty/websocket/jsr356/server/ServerContainer; used in the signature
which refers to the code
ServerContainer container = WebSocketServerContainerInitializer.configureContext(context);
I'm at a loss to figure this out. I'm using the following lines from gradle to bring in the websocket stuff:
providedCompile (
[ group: 'javax.websocket', name: 'javax.websocket-api', version: '+'],
[ group: 'javax.ws.rs', name: 'javax.ws.rs-api', version: '+' ]
)
compile (
[ group: 'org.eclipse.jetty.websocket', name: 'javax-websocket-server-impl', version: '+'],
[ group: 'org.eclipse.jetty.websocket', name: 'javax-websocket-client-impl', version: '+']
)
I see that both the javax-websocket-server-impl jar and the javax.websocket-api jar contain ServerContainer classes...but I'm only including one of those in my war file. Is jetty pulling from its own internal older version? Or am I completely misreading the source of the issue?
The jetty version I have is: jetty-9.2.1.v20140609
The websocket jars should not be in your WAR.
Remove the following jars from your WAR's WEB-INF/lib/ directory.
javax.websocket-api-*.jar - the javax.websocket API jar
javax-websocket-server-impl-*.jar - the jetty server javax.websocket.server.* implementation jar
javax-websocket-client-impl - the jetty javax.websocket.* (client) jar
This is because you are coding/compiling against javax.websocket.* API classes.
The API and the implementation of the API are provided by Jetty itself.
This is no different than when you code against the servlet-api. (namely, that you don't include the servlet-api and the implementation of the servlet-api in your WAR)