For a project I'm doing I'm trying to run OpenTelemetry (OTEL) in an OSGi-container. Hereby the situation:
I have a simple Maven/Java-application in which includes the #WithSpan-annotations via the io.opentelemetry.opentelemetry-extension-annotations dependency, version 1.12.0 (can ofcourse be changed). The application for now is fairly simple; it just calls different methods who are annotated and do some logging.
#WithSpan("multiple")
private static int multiple(int number) {
return number * 2;
}
The java-agent is successfully attached to the container via the start-up script
The collector pipeline is running successfully via a YAML-file, this has been verified by running the jar of another project with the agent against it. This collects the results and displays it in Jaeger.
However, due to the limited exports of the dependency, the main application was not able to run, because the dependency did not export its classes/methods/etc. Therefore I wrapped this as an OSGi-bundle. I did this as following:
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
<configuration>
<instructions>
<Bundle-Vendor>opentelemetry (Repackaged)</Bundle-Vendor>
<Embed-Dependency>
groupId=io.opentelemetry;artifactId=opentelemetry-extension-annotations;type=jar;classifier=;inline=true
</Embed-Dependency>
<Embed-Transitive>false</Embed-Transitive>
<Export-Package>*</Export-Package>
<Import-Package>!*</Import-Package>
<Private-Package>io.opentelemetry.*</Private-Package>
</instructions>
</configuration>
</plugin>
However when now having installed the wrapped OTEL-bundle in the container to which the agent is attached, and running the test project, I get the following error:
[otel.javaagent 2022-XX-XX XX:XX:XX:XXX +0000] [shell remote=/127.0.0.1:52855] WARN muzzleMatcher - Instrumentation skipped, mismatched references were found: opentelemetry-annotations [class io.opentelemetry.javaagent.instrumentation.otelannotations.WithSpanInstrumentationModule] on org.eclipse.osgi.internal.loader.EquinoxClassLoader#c89a9f[com.example.test-project:1.0.0.SNAPSHOT(id=15)]
And logically no spans show up in Jaeger. Does anybody have any suggestion? I tried to change the versions, include transitive dependencies, etcetera. But nothing seems to work.
I am building a Vaadin application with Java. Here is the folder structure.
- com
-- my
--- WebTool
---- ToolUI.java
---- View_1.java
---- View_2.java
The entry point to the application is ToolUI.java and has the method init() that takes VaadinRequest as a parameter. It is this file where I add the views Views_1 and View_2 as views of the application and add navigations among them. Everything runs great when I run the application via the Eclipse IDE.
Now I have a requirement that I have to deploy this application on a remote server. So I created a war of the project and deployed on the server by the name
MyWebTool.war.
Now when I try running the war with the command
java -jar MyWebTool.war
it gives me the error: Can't execute war no main manifest attribute, in MyWebTool.war
I am not sure what to add the main class as since the init method gets invoked and sets the app running. So I put a blank main function inside the MyWebToolUI.java and added this dependency in the pom.xml file.
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-war-plugin</artifactId>
<version>2.6</version>
<configuration>
<archive>
<manifest>
<addClasspath>true</addClasspath>
<mainClass>com.my.WebTool.ToolUI</mainClass>
</manifest>
</archive>
<failOnMissingWebXml>false</failOnMissingWebXml>
<!-- Exclude an unnecessary file generated by the GWT compiler. -->
<packagingExcludes>WEB-INF/classes/VAADIN/widgetsets/WEB-INF/**</packagingExcludes>
</configuration>
</plugin>
But now when trying to run the application it says Could not find or load main class com.my.WebTool.ToolUI
Can please somebody shed light on this? I don't know if I am missing something simple here but at this point, I am stuck. Thanks a lot.
For running war packaged applications, you will need a servlet container.
The servlet container provides all the basic infrastructure needed to run java based web applications.
One of the most common ways to do this, is to deploy the war file to a tomcat installation.
My current project consisting of a war and ejb module, is using a jar (incorperated via maven). This jar contains a CDI component which, when I inject this in the war module it works as expected, but when I inject this in my ejb module I get a NoClassDefFoundError during startup from my WAS 8.5 in eclipse (full profile).
When I start the server first, add the inject later and republish it seems to work. Also when I use Liberty profile it works. Also on Z/os and IPAS it works as expected.
I think it might has something todo with classloading, but have no idea how to solve this properly.
Using Eclipse Neon, WAS 8.5.5.11 full profile , jee6
Project is using java 8 while the component is using java 6
This is the first part of the stacktrace:
[13-9-17 14:54:26:589 CEST] 0000003e InjectionProc W CWNEN0047W: Resource annotations on the fields of the BestelFacade class will be ignored. The annotations could not be obtained because of the exc
eption : Logger
at java.lang.Class.getDeclaredFieldsImpl(Native Method)
Thanks
I found a way to get the job done, but I'm not sure if this is a proper solution or just a workaround while masking the real problem.
When I take a look at the ear module assembly I see in the source column c:/ws/.../jar and in the deploy path lib/jar
when I change the source into /..ear/target/../jar it works
Try setting the <bundleDir>/</bundleDir>
This will place the external jar/ejb not in lib, but in the root.
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-ear-plugin</artifactId>
<configuration>
...........
<defaultLibBundleDir>lib</defaultLibBundleDir>
<modules>
<jarModule>
<groupId>groupId</groupId>
<artifactId>artifactId</artifactId>
<bundleDir>/</bundleDir>
</jarModule>
</modules>
</configuration>
</plugin>
I my application I am facing below exception,
/component/ProviderServices;Lcom/sun/jersey/core/spi/factory/InjectableProviderFactory;)V
at com.sun.jersey.api.client.Client.<init>(Client.java:212)
at com.sun.jersey.api.client.Client.<init>(Client.java:150)
at com.sun.jersey.api.client.Client.create(Client.java:476)
at com.example.data.DataReader.getData(DataReader.java:25)
at com.example.data.TestServlet.doGet(TestServlet.java:41)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:620)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:727)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:303)
I found the reason for this exception but I don't know how to resolve it. The problem is I am having two jars namely jersey-bundle-1.1.5.1 and jersey-core-1.17.1 in my classpath. ContextResolverFactory.java is present in both jars with same package name. init method is present in jersey-core-1.17.1 but not in jersey-bundle-1.1.5.1. In windows build environment it is working fine. That means the JRE picks the ContextResolverFactory.java of jersey-core-1.17.1 correctly and executes the init method. Whereas in linux environment the JRE picks ContextResolverFactory.java of jersey-bundle-1.1.5.1 and tries to invoke the init method and throwing the above exception. I cant remove a jar blindly, since both jars are needed for different business purpose.
How to fix it in both linux and windows environment?
Why it is working fine in windows environment but not in linux environment?
I fully agree with the commenters. Per se it is bad practice to have the same class (in the same package) on the classpath multiple times. This will almost always cause troubles. The best thing would be to check whether or not you can make your code work with jersey 1.17.1 and use only the jersey-core-1.17.1 jar.
However, I also understand that there are situations where you do not have control over these dependencies i.e. where 3rd party libraries depend on specific versions of a certain library and you just have to work around these issues.
In these cases it is important to notice that the default java classloaders respect the order of the elements in the classpath. I assume that the order of the CLASSPATH variable in your Linux installation is different from that on your Windows installation.
If you are using an IDE such as Eclipse during your development please check the build path setup there and try setting the CLASSPATH variable on your production in exactly the same order.
For your reference please also check these other questions on stackoverflow:
Controlling the order of how JARs are loaded in the classpath
Is the order of the value inside the CLASSPATH matter?
In the case of Tomcat the order of the JAR files in WEB-INF/lib cannot be defined. The only thing you could do here would be to ship the JAR file that needs to be loaded first to some other directory in your production environment such as the JRE/lib directory, the Tomcat/common directory or the Tomcat/shared directory. Which all have priority over the WEB-INF/lib directory. See Control the classpath ordering of jars in WEB-INF/lib on Tomcat 5? for details on how this worked on older Tomcat versions.
One of the guiding principles that I try to follow when I develop my own applications is that I want to make them "dummy-proof." I want to make it as easy as possible on the end user.
Therefore, I would change the build of the applications to include ContextResolverFactory.class in your final jar (from jersey-core-1.17.1.jar). That's the general approach. The specific tool you use to achieve this might vary.
I would use maven and the maven-shade-plugin. This plugin can even do what's called a relocation where you provide the original package in the pattern tag, and you provide the desire new package location in the shadedPattern tag:
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>1.6</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
<configuration>
<relocations>
<relocation>
<pattern>com.sun.jersey.core.spi.factory</pattern>
<shadedPattern>${project.groupId}.${project.artifactId}.com.sun.jersey.core.spi.factory</shadedPattern>
</relocation>
</relocations>
<artifactSet>
<includes>
<include>com.sun.jersey:jersey-core</include>
</includes>
</artifactSet>
<minimizeJar>true</minimizeJar>
</configuration>
</execution>
</executions>
</plugin>
</plugins
</build>
Even if you're not experienced with maven, you could still make a small side project whose only purpose is to refactor the package location. Then, you would add this dependency to your project and use it to reliably access the init() method.
If you are experienced with maven, then I highly recommend splitting your project up into what's called a maven multi module POM project. This would be the new build order:
The Interface module
The Implementation Layer
The Runtime module
Where the Implementation Layer typically consists of many different modules that all depend upon the Interface module. And the Runtime module chooses the correct implementation at runtime.
You might not see the value if you currently only have one implementation... But down the road, it adds flexibility if you need to add more implementations, because you will be able to add them easily. Because your code never directly references an implementation, but rather, it always uses the interface, and it doesn't care which implementation is used.
So, this would make it harder on you, the developer, but easier on the end-user. Whether they're on windows, linux, or mac, it just works!
After checking the source-code, I noticed that all the logic of init() was moved to the constructor.
So another option, is to simply use the new constructor and catch the exceptional circumstance where it's not there, in which case, you would just use the default constructor followed by the init() method:
ContextResolverFactory factory = null;
try {
factory = new ContextResolverFactory(providerServies, ipf);
} catch (InvalidClassException ex) {
factory = new ContextResolverFactory().init(providerServices, ipf);
}
// ...
ContextResolver<MyType> cr = factory.resolve(type, mediaType);
if (cr == null) // handle null and not null...
Hopefully this helps. Good luck!
I'm evaluating Spring MVC & Boot and AngularJs for building web applications. I've run into the problem that when I make modifications to my static content (html, js, css), I have to restart the application every time. I hope there is a some way of solving that because restarting the whole application for static content changes is not efficient. Every other web app framework I've tried allows updating static content files on the fly(even just Spring MVC and plain old WAR application).
I've setup my project from "Building a RESTful Web Service with Spring Boot Actuator" guide (http://spring.io/guides/gs/actuator-service/). Basically it uses Spring Boot and MVC controllers to create a REST service. In addition, I've used "Consuming a RESTful Web Service with AngularJS" guide (http://spring.io/guides/gs/consuming-rest-angularjs/) to build a frontend with AngularJS. It creates a web page that displays the response from the REST service. The only change I've made is that the requests are made to my application instead of "http://rest-service.guides.spring.io/greeting". My static content is stored in "src/main/resources/public" folder. This setup works correctly except it doesn't reload static content.
A recap of the original problem
I've run into the problem that when I make modifications to my static content (html, js, css), I have to restart the application every time
I had the same problem and finally solved it by adding
<configuration>
<addResources>true</addResources>
</configuration>
to spring-boot-maven-plugin in the pom.xml
I got confused by this spring-boot-devtools thing, but it had no effect whatever I did.
My static content is stored in "src/main/resources/public" folder.
Your path is just fine. src/main/resources/static is also fine.
Ah ... I came across this issue too.
Instead of putting your static content in the classpath src/main/resources/public folder, put them in src/main/webapp, the same as you would any other Java web app. The embedded Tomcat will automatically reload them whenever they change.
As mentioned in the comments, the default configuration will not include the resources that are in src\main\webapp. To get around this issue, you can just add the following to your pom.xml <build> node:
<plugin>
<artifactId>maven-resources-plugin</artifactId>
<version>2.6</version>
<executions>
<execution>
<id>copy-resources</id>
<phase>validate</phase>
<goals>
<goal>copy-resources</goal>
</goals>
<configuration>
<outputDirectory>${basedir}/target/classes/static</outputDirectory>
<resources>
<resource>
<directory>src/main/webapp</directory>
<filtering>true</filtering>
</resource>
</resources>
</configuration>
</execution>
</executions>
</plugin>
By using the resources plugin, you are able to do your local development by running the executable JAR:
java -jar target/.jar
While that is running you can use Chrome Dev Tools or whatever IDE you like for modifying the files, without restarts. However, whenever you run your build, then the package generated will include all of the files under src\main\webapp in src\main\resources\static.
The docs say "all modern IDEs allow reloading of static resources and usually also hot-swapping of Java class changes" (https://docs.spring.io/spring-boot/docs/current-SNAPSHOT/reference/html/howto.html#howto-hotswapping). It's true. Eclipse does it more or less by default, and I'm not an IntelliJ user, but from what I understand you can configure it to build automatically as well.
A colleague and I came across this issue as well. We found the answer in the IntelliJ documentation...
On the main menu, choose Run | Reload Changed Classes
My solution (written in Kotlin but is quite obvious):
#Controller
class WebController : WebMvcConfigurerAdapter() {
override fun addResourceHandlers(registry: ResourceHandlerRegistry) {
System.getProperty("resources.local.path")?.let {
registry.addResourceHandler("/**").addResourceLocations(it)
}
}
...
}
Main idea is you can add your own resource handler conditionally. E.g. if some system property is set (resources.local.path) then add resource location with value from the property. Then you set this property in development with some reasonable value like '-Dresources.local.path=file:/Users/andrey/Projects/gsp-test/src/main/resources/static/'.
Do not forget trailing slash.
I am using 1.5.8.RELEASE.
It instantly updates my changes especially static files or jsp files.
If you are using Maven. You need to add this in pom.xml
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<optional>true</optional>
</dependency>
And you have to start Spring Boot with this:
mvn clean spring-boot:run
Full example and more detail here https://www.surasint.com/spring-boot-with-auto-update-changed-files-example/
#eigil metioned addResources config for maven build. I'm using spring-boot-gradle-plugin in a gradle build, and I found this Spring Boot github issue
, and the Spring Boot doc mentioned this option too. Just add this directive to build.gradle and run Gradle task bootRun, then resource file refreshes immediately when saved. FYI.
I had the same issue , the solution proposed here seems logical and worked for me
in breif :
1- ctrl+shift+A
2- search for registry
3- in the opened dialogue search for "compiler.automake.allow.when.app.running"
and check it
http://garywaddell.com/2015/11/20/spring-boot-intellij-idea-not-reloading-static-content/
For eclipse you have to activate the Project -> "Build Automatically" option as a minimum configuration.
What I ended up using was Browsersync with grunt. browsersync and grunt watches your static resources on disk and updates the browser when you edit the files. It acts as a kind of proxy. This way you can see changes in UI immediately without building or restarting anything.
Grunt, browsersync, spring boot and angularjs are configured for you if you use JHipster which I used to setup my project.
Granted this requires a lot more tools than just an IDE and is a lot more complicated so I wouldn't recommend this for every project.
spring-boot-devtools is not the solution to "hot deploy" of edited static htm/js
I configured a web facet inside intellij so that when I use it to edit html/js file inside resources/static, intellij then knows to copy the updated file to ./target and the spring boot application I have launched inside the automatically displays that content
see
https://www.jetbrains.com/help/idea/2016.2/configuring-static-content-resources.html
The Java version of #viator 's answer:
#Configuration
class WebMvcConfigurer extends WebMvcConfigurerAdapter {
#Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/dist/*.js").addResourceLocations(
"file:src/main/typescript/dist/"
);
}
}
You can do it by just adding one more dependency
you Gradle
compile group: 'org.springframework.boot', name: 'spring-boot-devtools', version: '1.3.0.RELEASE'
In you Pom.xml
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<version>1.3.0.RELEASE</version>
</dependency>
You have two possebilities how to serve static webcontent
From the classpath (per default src/main/resources/static
or src/main/resources/public or META-INF/resources/)
From the file system (per default src/main/webapp)
If you pick solution 1) - you can safely copy the jar around as the static web content is within that jar. If you want that the server picks up changes, you need to do (auto)hotswapping.
If you pick solution 2) - everything will work out of the box, every change will be automatically picked up. HOWEVER - if you copy the final jar to a different location - things will stop working. That is unless you specify an absolute path in application.properties. For example:
spring.resources.static-locations=file:///C:/myspringbootapp/src/main/webapp
So solution 2) is easier but less portable. Solution 1) is portable but more difficult to use(ide config).
For Spring Boot 2+ with gradle Kotlin dsl:
tasks.bootRun {
sourceResources(sourceSets.getAt(SourceSet.MAIN_SOURCE_SET_NAME))
}
thanks to #briskr's answer for the gradle dsl version :)
I had the same problem with live reloading of static contents in my SpringBoot porject: Now from various solutions posted in StackOverflow, I am able to get the solution. Following are the tools I used for development: IntelliJ Idea & Google Chrome in Ubuntu 18.04
I did the following:
Kept the templates folder in resourses folder itself. (Some solutions I found it to be kept in webapp folder under the main, but I did not get the result)
Add this configuration
<addResources>true</addResources>
</configuration>
to spring-maven-plugin in your POM file.
3.Please don't forget to add this dependency to POM file
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
<optional>true</optional>
</dependency>
Add the Live Reload extension to your web browser.
Restart the server using ' mvn clean spring-boot:run ' (only then the changes will be reflected in the build). During server startup you can see the message Live Server started at ....
Load the page using localhost:8080/... and click the LiveReload extension to connect it with the server.
Make any change to your static HTML file in the resources/ templates folder. Save it and check the webbrowser again, it will be reflected there...