I have a Java class that has a #WebService annotation and is packaged in a WAR. When deploying the WAR to different JavaEE 6 application servers I want to have the same URL (of course with different hosts and ports...).
The default naming seems to be appserver-dependent. Some examples:
Glassfish:
http://{hostname or ip}:{port}/{service name}/{port name}
JBoss:
http://{hostname or ip}:{port}/{ejb-jar-name}/{service name}/{port name}
WebSphere:
http://{hostname or ip}:{port}/{ejb-jar-name}/{service name}
What is the easiest way for configuring this for all server vendors?
If you are creating a web service based in a POJO class, then you only need to pack your war file inside an ear file and define the context root of the web module in the application.xml configuration file.
Here is an application.xml file example:
<?xml version="1.0" encoding="UTF-8"?>
<application xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/application_5.xsd" version="5">
<display-name>simple-ws-app</display-name>
<module>
<web>
<web-uri>simple-ws-war.war</web-uri>
<context-root>/simple-ws-app</context-root>
</web>
</module>
<library-directory>lib</library-directory>
</application>
In the annotation #WebService you can configure the expected web service configuration, if you have a wsdl file then is easier to define the web service. Here is an example of the complete #WebService annotation configuration, use only the properties you need.
#WebService(name = "SimpleService",
serviceName = "SimpleService",
portName = "SimpleServicePort",
endpointInterface = "simple.ws.srv.SimpleServicePortType",
targetNamespace = "http://www.ws.simple/srv",
wsdlLocation = "WEB-INF/wsdl/simple-ws.wsdl"
)
Note that if you are using a wsdl file the default location to place it is inside WEB-INF/wsdl.
Now, the expected wsdl URL for this configuration is
http://hostname:port/simple-ws-app/SimpleService?wsdl
This may not work fot all app-servers, I know it works for Glassfish, WildFly and Weblogic.
Finally, the default naming for enterprise web services (for example EJB WebServices, ejb-jar inside ear file) is in deed appserver-dependent. I've been googling and trying to accomplish this configuration for several months with the same result. No matters if you provide a complete #WebService annotation configuration including a valid wsdl with the expected endpoint configuration, app-servers override the wsdl endpoint URL.
Related
I have implemented a basic EJB Object in my code. Then I created a jar for this ejb. The jar file contains:
package containing the ejb classes (home interface/remote bean interface/bean implementaion)
META-INF folder containing the ejb-jar.xml
ejb-jar.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE ejb-jar PUBLIC "-//Sun Microsystems, Inc.//DTD Enterprise JavaBeans 2.0//EN" "http://java.sun.com/dtd/ejb-jar_2_0.dtd">
<ejb-jar>
<display-name>NewTransactionEjb</display-name>
<enterprise-beans>
<session>
<display-name>NewTransactionEjb</display-name>
<ejb-name>NewTransactionEjb</ejb-name>
<home>gr.cosmote.mdb.NewTransactionEjb.NewTransactionEjbHome</home>
<remote>gr.cosmote.mdb.NewTransactionEjb.NewTransactionEjb</remote>
<ejb-class>gr.cosmote.mdb.NewTransactionEjb.NewTransactionEjbBean</ejb-class>
<session-type>Stateless</session-type>
<transaction-type>Container</transaction-type>
</session>
</enterprise-beans>
<assembly-descriptor>
<container-transaction>
<method>
<ejb-name>NewTransactionEjb</ejb-name>
<method-name>*</method-name>
</method>
<trans-attribute>NotSupported</trans-attribute>
</container-transaction>
</assembly-descriptor>
</ejb-jar>
Then I deployed the EJB by placing the jar in webapps folder and from the server logs it seems to have been deployed successfully.
But when I try to reference the ejb from my code I get error.
Code:
Properties p = new Properties();
p.put(Context.INITIAL_CONTEXT_FACTORY, "org.apache.openejb.core.LocalInitialContextFactory");
InitialContext context = new InitialContext(p);
ejbHome = (EJBHome) context.lookup("java:global/NewTransactionEjb/NewTransactionEjb");
I have used "java:global/NewTransactionEjb/NewTransactionEjb" because upon ejb deployment I see this line in the server logs:
03-Sep-2021 17:31:23.628 INFO [Catalina-utility-1] org.apache.openejb.assembler.classic.JndiBuilder.bind Jndi(name=global/NewTransactionEjb/NewTransactionEjb!gr.cosmote.mdb.NewTransactionEjb.NewTransactionEjbHome)
--> Ejb(deployment-id=NewTransactionEjb)
In the execution it seems the the above code is working and it retrieves the EJBHome, but when I try to
cast it to my own home interface class it fails with the following error:
java.lang.ClassCastException: com.sun.proxy.$Proxy362 cannot be cast to
gr.cosmote.mdb.NewTransactionEjb.NewTransactionEjbHome
What am I doing wrong?
I have finally found the solution to this issue. To be precise the actual problem has nothing to do with the exception which is just confusing. So I will mention my problem anyway, in case someone faces the same issue.
My problem was that 2 of the EJB classes (home interface and remote bean interface) were also in TOMEE /lib directory except for the EJB deployable jar file which was placed in /webapps directory. So I removed them from the jar file (now it contains only the bean implementaion class), deployed it and everything is working fine.
I have a Java web application using Wicket 6, Spring 3.2 and WildFly 8.2.0. Right now i'm setting the context root of my web application in the jboss-web.xml file like this:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE jboss-web PUBLIC "-//JBoss//DTD Web Application 5.0//EN" "http://www.jboss.org/j2ee/dtd/jboss-web_5_0.dtd">
<jboss-web>
<context-root>/myCustomContextRoot</context-root>
</jboss-web>
The jboss-web.xml file is compiled into the war. Now some clients want to change this context root to an empty context root. So i hace to recompile a version of my app per different context root. Is there a way to set the context root of my application from outside .war, programatically from a .properties file, or any other way for example in standalone.xml of WildFly 8.2.0?
Set the runtime name when deploying your web application. Suppose your WAR is called myapp-1.0.0-SNAPSHOT.war. Using a runtime name of foo.war, the context root will be /foo.
Using a runtime name of ROOT.war, the context root will be /.
The runtime name can be set when deploying via the Web Console or via the CLI.
Thanks for your Answer Harald Wellmann. It answers the question and pointed me into the right direction!
Some things I had to find out on my own and which may help others:
the exact syntax in jboss-cli to specify a runtime-name is:
deploy path_to_war_file --runtime-name=wantedName.war
This leads to a context-root of /wantedName/ for the webapp.
The runtime-name does not have any effect on the context-root, if the war file contains a jboss-web.xml in WEB-INF which in turn contains a context-root tag.
That is, if you want to control the context-root of your web-app in WildFly at deployment time, you must not specify any context-root in jboss-web.xml.
It is ok to have a jboss-web.xml without a context-root tag if you want to take advantage of the runtime-name to control the context-root.
I tested this on WildFly 9.0.1 and 9.0.2:
Hope this helps!
I have a java application which needs to be deployed in the weblogic server. I am currently making the ear file for that application. My ear file has an ejb jar inside. I want to add log4j2 jars to this application. So my folder structure is
> Project-Name-
> --Ear-Content
> --APP-INF
> --lib -> log4j2 jars
> --classes - > log4j2.xml
> --META-INF->application.xml, MANIFEST.MF, weblogic-application.xml
> --Project-Name.jar
Currently I have put the jars in APP-INF folder/lib and in META-INF/application.xml I have put the jars in modules. Here is my application.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE application PUBLIC '-//Sun Microsystems, Inc.//DTD J2EE Application 1.3//EN' 'http://java.sun.com/dtd/application_1_3.dtd'>
<application>
<display-name>ProjectName</display-name>
<description>ProjectName</description>
<module>
<ejb>ProjectName.jar</ejb>
</module>
<module>
<java>lib/log4j-api-2.1.jar</java>
</module>
<module>
<java>lib/log4j-core-2.1.jar</java>
</module>
</application>
But it is not taking the log4j jars. Any solutions ??
If you are only packaging up one application, I would highly recommend using a war file instead of an ear since it is simpler. Otherwise you may need to package your current Project-Name.jar into a war file and then package that into the ear.
See a tutorial like the one here
That said - you should not need to explicitly reference the log4j libraries in your application.xml file with module tags. From the Oracle docs:
The classes and libraries stored under APP-INF/classes and APP-INF/lib
are available to all modules in the Enterprise Application. The
application classloader always attempts to resolve class requests by
first looking in APP-INF/classes, then APP-INF/lib.
Last but not least, if it seems like Weblogic is not using the classes you want it to and is instead using the defaults, in your case log4j 1.2 vs log4j 2, you will need to set the following in your application.xml to tell Weblogic which one to use:
<prefer-application-packages>
<package-name>org.apache.log4j.*</package-name>
</prefer-application-packages>
I'm developing a web application, which consists of two independent parts - the authentication and the real application part. Both parts are WARs which are deployed at (currently) one Tomcat 7 instance.
So, I have the following two WARs in my webapps folder:
webapps
|
+- BloggofantAuthentication
|
+- Bloggofant
until now they are available at http://127.0.0.1:8080/BloggofanAuthentication and http://127.0.0.1:8080/Bloggofant. Is it possible proxy the WARs at Tomcat directly (so that I don't have to use Apache httpd and its mod_proxy module)? So that in the end, the WARs at the server are reachable as follows:
http://127.0.0.1:8080/BloggofantAuthentication -->
http://127.0.0.1/bloggo/
http://127.0.0.1:8080/Bloggofant -->
http://127.0.0.1/bloggo/fant/
Any suggestions on this topic are highly appreciated ;)
EDIT
Here are the context.xml files of the two unpacked webapp WAR folders:
webapps/BloggofantAuthentication/META-INF/context.xml
<?xml version="1.0" encoding="UTF-8"?>
<Context path="">
<!-- Comment this to enable session persistence across Tomcat restarts -->
<Manager pathname=""/>
</Context>
webapps/Bloggofant/META-INF/context.xml
<?xml version="1.0" encoding="UTF-8"?>
<Context path="/bloggofant">
<!-- Comment this to enable session persistence across Tomcat restarts -->
<Manager pathname=""/>
</Context>
If I now want to access my apps via http://127.0.0.1:8080 or http://127.0.0.1:8080/bloggofant I get a 404 - Page Not Found error ...
You can configure the path at which Tomcat serves a web application using a context.xml file. You can put this in the WAR's META-INF directory, with the content:
<Context path="/bloggo/fant" />
And it will serve it there instead of at the default /Bloggofant path.
Note the warning about automatic deployment in the documentation:
When autoDeploy or deployOnStartup operations are performed by a Host, the name and context path of the web application are derived from the name(s) of the file(s) that define(s) the web application. Consequently, the context path may not be defined in a META-INF/context.xml embedded in the application
Elsewhere, the documentation tells us that these both default to true. Thus, you will need to set them to false for these settings to be respected.
My scenario is the following:
I have a WebApp.war that is deployed to a servlet container. This WebApp.war contains in WEB-INF/lib the following libraries:
lib_a.jar
lib_b.jar
I have one other library, say lib_vendor.jar, that I cannot deploy within WebApp/WEB-INF/lib because of licensing issues so I let our customers to copy this library in tomcat/lib after application installation. But since lib_vendor.jar requires lib_a.jar and lib_b.jar that are loaded in the web application class loader, I cannot use lib_vendor.jar.
How can I load an external library (not in WEB-INF/lib) in the same classloader of a web application?
Since you are using Tomcat, you could leverage the VirtualWebappLoader.
Add a META-INF/context.xml whith
<?xml version="1.0" encoding="UTF-8"?>
<Context path="/somepath/myapp">
<Loader className="org.apache.catalina.loader.VirtualWebappLoader"
virtualClasspath="/somedir/*.jar"/>
</Context>
Remember also that the virtualClasspath attribute must be a absolute path, as correctly stated in the comment below.