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.
Related
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.
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'm building a Spring web service, using IntelliJ (and Maven), and deploying it into a Tomcat container. When I run it locally, it deploys to the root application context. I'm wondering if there's a way that I can programmatically retrieve the name of the artifact deployed somewhere in code.
So here's what my Tomcat configuration looks like in IntelliJ:
In this example I called the service "image-service" and so it deploys "image-service:war". (Alternatively, I could have it deploy "image-service:war exploded".) I'm looking for a way to assign to a variable the literal string image-service:war, or at the very least image-service, automatically.
Is there any way to do this?
You need the web application context path. To get it, inject the HttpServletRequest object into your controller and use method getContextPath() to retrieve it.
If the war is deployed in the root context you will get an empty string. Otherwise, you will get the context path under which the application is deployed (in your case /image-service).
Edit: Additional explanation for the suggestion from comment:
To make build-time variables (e.g. artifact name) available to your application, you can put custom entries in the manifest file using maven-war-plugin:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-war-plugin</artifactId>
<version>2.2</version>
<configuration>
<archive>
<manifestEntries>
<distname>${project.build.finalName}</distname>
</manifestEntries>
</archive>
</configuration>
</plugin>
Then, you can read the artifact name from your code like this:
try {
Properties properties = new Properties();
properties.load(request.getServletContext()
.getResourceAsStream("/META-INF/MANIFEST.MF"));
String distName = properties.getProperty("distname");
} catch (IOException e) {
// Handle the exception
}
I've web application. I'm using maven to build this application. I get a war file when i build application: my-service-1.0.0-SNAPSHOT.war. While accessing the services over http, i have to make a call like this:
http://localhost:8080/my-service-1.0.0-SNAPSHOT/......
I don't want version number in my context name. I'm using tomcat as container. Do i have to set context root for this under Web-Inf as we do it in case of jboss ? Does it depend based on the type of container we use ?
Using maven you can set a variable in your pom.xml file to store your final build name and in your war plugin configuration you pass it. Something like this:
<build>
<finalName>my-service</finalName>
</build>
Then in your plugin configuration:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-war-plugin</artifactId>
<version>2.0</version>
<configuration>
<webappDirectory>/path_to_deploy_folder/${project.build.finalName}.war</webappDirectory>
</configuration>
</plugin>
You did not mention whether you are using maven to deploy into tomcat container. If you're creating a production environment you probably won't be using maven at least for local deployments. In that case I don't think it's a bad idea to rename your war file. For example if you want you webapp root to be at https://mydomain.com/subdomain/myteam/myapp then simply rename my-service-1.0.0-SNAPSHOT.war to subdomain#myteam#myapp.war with '/' being replaced by '#'
we have an "old" JavaEE Application, which we want to port from the old Sun Application Server 9.1 to the current Glassfish 3.1. We updated the deployment descriptor xml files (renamed them, updated DocType, validated against DTD, nothing else). But when we try to the deploy into the GF3.1 we get this error:
JDO83008: CMP Compilation failed:
C:\workspace\glassfish31eclipsedefaultdomain\generated\ejb\archivetool-app-1.9.5\archivetool-ejb-1.9.5_jar\de\ems\archivetool\ejb\metadata\cd\eb\CdBean_821611534_ConcreteImpl.java:10:
cannot access de.ems.archivetool.ejb.framework.AbstractCMPBean
class file for de.ems.archivetool.ejb.framework.AbstractCMPBean not found
C:\workspace\glassfish31eclipsedefaultdomain\generated\ejb\archivetool-app-1.9.5\archivetool-ejb-1.9.5_jar\de\ems\archivetool\ejb\productdata\product\eb\ProductionLibraryBean40992531_ConcreteImpl.java:416:
cannot find symbol
symbol : class EBSBusinessException
location: package de.ems.archivetool.ejb.framework
WARNUNG: JDO83004: CMP Compilation failed. See log for details.
SCHWERWIEGEND: Exception while invoking class org.glassfish.ejb.startup.EjbDeployer prepare method
SCHWERWIEGEND: Exception while invoking class org.glassfish.javaee.full.deployment.EarDeployer prepare method
SCHWERWIEGEND: Exception while preparing the app
SCHWERWIEGEND: JDO83004: CMP Compilation failed. See log for details.
org.glassfish.deployment.common.DeploymentException: JDO83004: CMP Compilation failed. See log for details.
But we can still deploy in the old SUN App Server.
The application consists of 4 modules and a build module. Generally, the .ear file, consisting of the two EJB modules, one WAR module and one JAR module, is build with Maven without problems (UnitTest succeed etc).
(pom.xml and the resulting application.xml)
So, everything builds fine, but when we try to deploy the application to GF3.1 we get the "class file not found" error. The classes which are not found are within the JAR module and contain base classes for the EJB modules.
Does anyone has a starting point?
Regards,
Andreas
Ok, after hours of googeling, I finally found the exact answer to this problem here.
The important part is:
The Java EE 6 specification imposes strict rules about which JAR files
are visible from an enterprise archive (EAR) file. Refer to section
EE.8.3.3; specifically, application client modules should not have
access to any EJB JAR file unless the application client JAR file's
manifest Class-Path refers to the EJB JAR file(s) explicitly.
This is a change from GlassFish Server v2, in which application
clients automatically had access to all EJB JAR files in the EAR file
and all JAR files at the top level of the EAR file. To comply with the
stricter specification language, GlassFish Server 3.0.1 cannot
automatically provide application clients with access to these JAR
files.
What you have to do is, let maven put the jar (and other dependencies) into a library folder in the ear container. You do this by adding this to your ear pom.xml:
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-ear-plugin</artifactId>
<configuration>
//here starts the important part
<defaultLibBundleDir>lib</defaultLibBundleDir>
<archive>
<manifest>
<addClasspath>true</addClasspath>
</manifest>
</archive>
//end of important part
<modules>
<jarModule>
<groupId>gID</groupId>
<artifactId>aID</artifactId>
</jarModule>
//etc some more ebjs, war, ...
</modules>
This will put the jar module into a folder lib, and all depending ejbs will get the Class-Path entry in their MANIFEST.MF.
Hope that helps some of you with the same problem.