I have a project with more than an hundred external library dependencies, here we use tomcat with this endorsed jar libs configured on a directory in the server (now is under $CATALINA_HOME/lib/endorsed), so the webapp can access those resources on runtime start.
I wanted to try jetty instead, because tomcat takes too much memory and crashes frequently. Now I'm wondering if there is a parameter to pass on maven-jetty-plugin to specify this jar's folder so as the webapp class loader find them in its classpath.
I've tried extraClasspath in configuration tag, but it seems to load only classes and ignore all jars in the directory I set into (if I pass the full name path of the jar, it is loaded, but I don't want to set every library that I need there).
Thanks in advance for the help
update:I know it's not a standard maven operation, i'm searching for an emergency workaround since this project is very huge and I can't refactor as I want.
But also I expected this feature was not as tricky as it seemed to me at first glance.
You need to pass them as absolute paths, or, alternatively, have them as dependencies of the plugin itself.
What you want to have done goes against Maven's portability principles, so don't expect it to support it.
Related
I am trying to do a log4j migration for a legacy application. I made the changes to the configuration files and tested it locally with Tomcat, where the logs were displayed correctly. However when I deploy on WAS, the logging stops.
I checked a lot of pages about the necessary dependencies and the possible problems, but now I feel I'm stuck. Here is what I already tried:
Added the log4j jars manually to the lib/ext directory in WAS (together with commons-logging, I read an article where it helped, although all these jar-s were already present in the ear)
Double checked, that the configuration file is on the classpath and that it's syntax is correct
Added logj42-web dependency
Added the necessary filters in web.xml (Spring version is 3.8, so also the config listener with the config name context-param)
Checked classloader in WAS - it's parent first
Am I missing something?
Any ideas are appreciated. Thank you in advance!
WAS includes its own commons-logging API (that does not utilize Log4j), so bringing your own logger requires a bit of extra class-loader-related config. Typically, that would go something like this:
Put your commons-logging and log4j jars, along with your logging properties files, in some directory (not WAS_HOME/lib/ext) readable by the user running the server.
Create a shared library on the server, with that directory as its class path, and select the "use an isolated class loader" option. Associate that shared library with your application or web module.
Ideally, that should be it. Isolated shared libraries search themselves before delegating to the server's loaders, so your application will "see" the commons-logging/log4j classes in the shared library instead of in the server, and likewise, it should pick up the configuration files from that directory instead of the ones found in the server.
You can also accomplish this same basic thing by leaving all the logging stuff in your WAR or EAR and setting its class loader to parent-last (which causes the class loader to search locally before delegating to the server-level loaders), but that is a bit riskier configuration - if your application includes APIs that are also provided by the server, parent-last class loading increases the possibility of ClassCastExceptions or LinkageErrors.
I´m currently building a spring-boot application, which also uses some javascript-stuff. I use yarn as a package-manager to manage the different js-libraries.
Now I wonder, how I would include these resources into my spring-boot-project? Simply including the whole node_module-folder as a resource seems to be overhead for me, as this doesn´t neccessarily contain only the required sources (for me it is more like my local maven-repo-path). How do I identify, which java-script-resources should be included in my jar in the end, so that I can also reference them in my Thymeleaf-HTML-templates.
I already found the 'frontend-maven-plugin' (https://github.com/eirslett/frontend-maven-plugin) which helps me to install all my yarn-dependencies during build, but it doesn´t care about the build-process, as far as I can see.
Thanks for your help!
Perhaps you should consider using webpack or some other javascript bundler/task runner to bundle your javascript and required dependencies into a single file. Then you can simply include that bundled file in your jar. For example: http://justincalleja.com/2016/04/17/serving-a-webpack-bundle-in-spring-boot/
Can anyone explain how Spring decides where to look for resources when one uses the ResourceLoader.getResource(...) method?
I am having a problem with a multi-module maven application built using Spring Boot whereby in my integration tests my code is able to find resources using resourceLoader.getResource("templates/") or even resourceLoader.getResource("classpath:templates/"). So far so good...
However, when the module is eventually packaged into the executable JAR and run with embedded Tomcat the resources can no longer be resolved. I also tried resourceLoader.getResource("classpath*:templates/") with no success.
What I find concerning is that when I add a logging statement to output the URL being used in the search i get a path to one of the other modules in the project (not the one that actually contains the resource in question). E.g: jar:file:/Users/david/exmaple/target/spring-boot-0.0.1-SNAPSHOT.jar!/lib/module1-0.0.1-SNAPSHOT.jar!/templates/ whereas I believe the resource is in jar:file:/Users/david/exmaple/target/spring-boot-0.0.1-SNAPSHOT.jar!/lib/module2-0.0.1-SNAPSHOT.jar!/templates/
The resource loader was obtained from an Autowired constructor param.
Thanks in advance for any hints.
Edit
Just in case it isn't clear or is of importance, my integration tests for the module in question aren't aware of the other module. I have module1, module2 and a spring-boot module which has dependencies on module1 & module2. Essentially, when I run the integration tests for module 2 the classpath isn't aware of module1 - so I suspect that this has something to do with why it works in the tests.
When you use classpath: or classpath*: prefix, internally, this essentially happens via a ClassLoader.getResources(…) call in spring.
The wildcard classpath relies on the getResources() method of the underlying classloader. As most application servers nowadays supply their own classloader implementation, the behavior might differ especially when dealing with jar files. A simple test to check if classpath* works is to use the classloader to load a file from within a jar on the classpath: getClass().getClassLoader().getResources("<someFileInsideTheJar>"). Try this test with files that have the same name but are placed inside two different locations. In case an inappropriate result is returned, check the application server documentation for settings that might affect the classloader behavior.
Do not use classpath: form as you have multiple classloader locations of templates/ .
Refer to: resources-classpath-wildcards
I'm working on a project that uses two maven projects (named core and webapp); core is built with JAR packaging and used for two different purposes: as a stand-alone app (essentially an executable JAR), and also embedded into webapp.
For its purpose as a stand-alone app, core needs to have its own logback configuration (a logback.xml file) that needs to be included on the classpath. Normal Maven convention would have me put it in src/main/resources/logback.xml. That works fine, but causes a problem when the core JAR is included in webapp. webapp needs to have its own logback configuration, but the container (tc Server or Jetty) is picking up the one from core.jar first.
I realize that logback can be told about a custom config location via a system property (-D on the command line) but that's not viable in a app container like Tomcat or Jetty.
I've read some other people asking about this situation, but none of the solutions I've seen sits well with me. One solution involved setting up a context listener that runs early in the webapp initialization and explicitly configures logback based on a <context-param>. That's a bit brutish in my opinion, and probably a hard sell to my fellow dev team when log4j "just works" in this situation.
I'm far from a Maven expert, so I'm hoping there is some elegant way to get Maven to help me here. Or perhaps some logback extension or add-on that makes it more web-app friendly. Or even a clever idea that I haven't thought of.
There are a number of possible solutions, but the easiest is to put the file in its own module and mark the dependency as provided. The, conspire to have it on the classpath when running the standalone version of the app.
The solution that we ended up using was to leave only the common "non-app" pieces (code and configuration) in core and then extract the other "app" pieces into a new module (batch-app).
The logging configuration only lives in the 2 app projects (webapp and batch-app) that depend on core. core has a logback-test.xml configuration in it, but that's excluded from the JAR that maven builds (since it's in the src/test/resources folder).
I have an issue in loading jars in websphere server. Some of the jars are present in WEB-INF/lib and some are present in local hard drive(ex., c:\lib folder). How can i load all these jars, during the startup of the application. If WEB-INF jars are loaded, external jars are not getting loading and viceversa..Need help on this....
WebSphere has a hierarchy of classloaders, parent classloaders cannot see child classloaders, hence you get surprises when you put different aspects of your application in different places.
Never attempt to place application jars in WebSphere's own lib directory, and never adjust WebSphere's own class path. There is ana rchitected way to make external jars visible, I'll explain that in a moment.
There are three places that you can put JAR files so that they will be loaded. By far the the best is simply to place the JARs in WEB-INF/lib. You can specify the search order preference PARENT LAST so that these take prececdence over jars supplied by websphere - but note that some fundamental jars cannot be over-ridden You cannot replace the IBM security for example.
Second you can add jars to the root of the EAR file. Noe that the hierarchy comes into play now, WEB-INF/lib jars can see EAR jars but EAR jars cannot see WEB-INF/lib jars.
Finally you can specify a WebSphere "Shared Libarary". See the Info Centre for how, it's very easy through the console. A shared library has a classpath, you add jars to that. Then you allocate the shared libarary to individual applicaitons or whole servers.
Once again You WEB app can see the shared library, but i don't beleive taht the convers is true. Hence putting framework code in a shread library may not work for you.