WebContext is no longer honoured after migration from Jboss7 to WildFly10 - java

I am migrating a statless EJB exposed as a web service from JBoss7 AS to WildFly 10 (granted I am a bit late).
The web service used to be accessible by http://localhost:8080/vmwWS/vmw, moving to WildFly gets me http://localhost:8080//vmwWS/WSVMWBean and I haven't found a way to change this.
Here's the web service class
[...]
#Interceptors(TracingInterceptor.class)
#Stateless
#WebService(endpointInterface = "com.mydomain.WSVMW")
#WebContext(contextRoot="/vmwWS", urlPattern ="/vmw", authMethod="BASIC", secureWSDLAccess = false)
#SecurityDomain("JBossWS")
#RolesAllowed({ "Read", "Write" })
public class WSVMWBean implements WSVMW {
[...]
The Interface:
[...]
#WebService(name = "vmw")
#SOAPBinding(style = Style.DOCUMENT)
#Local
public interface WSVMW {
[...]
And the jboss-webservice.xml:
<?xml version="1.0" encoding="UTF-8"?>
<webservices xmlns="http://www.jboss.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.jboss.com/xml/ns/javaee http://www.jboss.com/xml/ns/javaee/jbossws-web-services_1_0.xsd"
version="1.1">
<context-root>vmwWS</context-root>
<port-component>
<ejb-name>WSVMWBean</ejb-name>
<port-component-name>WSVMWBean</port-component-name>
<port-component-uri>/vmw</port-component-uri>
<auth-method>BASIC</auth-method>
</port-component>
</webservices>
The logs say:
22:16:59,520 INFO [org.jboss.ws.cxf.metadata] (MSC service thread 1-8) JBWS024061: Adding service endpoint metadata: id=WSVMWBean
address=http://localhost:8080/<ejb-jar-name>/vmwWS/WSVMWBean
implementor=com.mydomain.WSVMWBean
serviceName={http://vmw.mydomain.com/}/vmwWS
portName={http://vmw.mydomain.com/}WSVMWBeanPort
annotationWsdlLocation=null
wsdlLocationOverride=null
mtomEnabled=false
How do I get the previous behaviour back?

To cut it short this is the diff which fixed it:
-import org.jboss.wsf.spi.annotation.WebContext;
+import org.jboss.ws.api.annotation.WebContext;
From here:
https://developer.jboss.org/wiki/JBossWS4MigrationGuide

Related

Weblogic 14c - webservice-description-name is not unique within weblogic-webservices

I am exposing my stateless ejb as web service using the annotations as follows:
#WebService(
name = "MyServicePort",
portName = "MyServicePort",
serviceName = "MyService",
)
#SOAPBinding(
style = SOAPBinding.Style.RPC
)
#Stateless(mappedName="MyServiceEJB", name = "MyServiceEJB")
public class MyServiceBean {
To define the context root in weblogic, I've defined the web service in weblogic-webservices.xml deployment descriptor as follows:
<weblogic-webservices
xmlns="http://xmlns.oracle.com/weblogic/weblogic-webservices"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.oracle.com/weblogic/weblogic-webservices http://xmlns.oracle.com/weblogic/weblogic-webservices/1.1/weblogic-webservices.xsd">
<webservice-description>
<webservice-description-name>MyService</webservice-description-name>
<port-component>
<port-component-name>MyServicePort</port-component-name>
<service-endpoint-address>
<webservice-contextpath>/mycontext</webservice-contextpath>
<webservice-serviceuri>/myservice</webservice-serviceuri>
</service-endpoint-address>
</port-component>
</webservice-description>
</weblogic-webservices>
However, weblogic is throwing the below error while deploying:
[ERROR] weblogic.wsee.ws.WsException: Error encountered while deploying WebService module 'myservice-ejb.jar'.
In weblogic-webservices.xml, webservice-description-name MyService is not unique within weblogic-webservices
Any clue what I am doing wrong here? This is the only bean/service in my web application and there is no other application deployed in weblogic (local instance).
I am able to resolve the issue by placing the webservices.xml with below contents into META-INF folder (next to weblogic-webservices.xml).
<webservices xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/javaee_web_services_1_4.xsd"
version="1.4">
<display-name>MyService</display-name>
<webservice-description>
<webservice-description-name>MyService</webservice-description-name>
<port-component>
<port-component-name>MyServicePort</port-component-name>
<wsdl-port xmlns:tns="http://schemas.mycompany.com/webservices/MyService">tns:MyServicePort</wsdl-port>
<service-endpoint-interface>mypackage.MyServiceBean</service-endpoint-interface>
<service-impl-bean>
<ejb-link>MyServiceEJB</ejb-link>
</service-impl-bean>
</port-component>
</webservice-description>
</webservices>
Hope it may help someone facing the same challenge.

#Resource annotation doesn't work in Tomact 10.0.10

Recently I tried Tomcat 10.0.10 and when trying to inject the connection pool as a JNDI resource find out that the #Resource annotation doesn't work.
Then I tried obtain it programmatically by creating a InitialContext and it worked. Initially I thought it was only for the java:comp/env/jdbc so I tried with a simple bean like below and tried to inject it with the #Resource annotation it didn't work again. When I try to obtain it programmatically by creating a InitialContext and it works. Then I check whether the #PostConstruct or #PreDestroy annotation works and found out that they also don't work.
package lk.ijse.test.tomcatdbcp;
public class Something {
}
<?xml version="1.0" encoding="UTF-8"?>
<Context>
<Resource name="bean/Something" auth="Container"
type="lk.ijse.test.tomcatdbcp.Something"
factory="org.apache.naming.factory.BeanFactory"
/>
</Context>
<?xml version="1.0" encoding="UTF-8"?>
<web-app metadata-complete="false" xmlns="https://jakarta.ee/xml/ns/jakartaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="https://jakarta.ee/xml/ns/jakartaee https://jakarta.ee/xml/ns/jakartaee/web-app_5_0.xsd"
version="5.0">
<resource-env-ref>
<resource-env-ref-name>bean/Something</resource-env-ref-name>
<resource-env-ref-type>lk.ijse.test.tomcatdbcp.Something</resource-env-ref-type>
</resource-env-ref>
</web-app>
package lk.ijse.test.tomcatdbcp;
import java.io.*;
import jakarta.annotation.PostConstruct;
import jakarta.annotation.Resource;
import jakarta.servlet.http.*;
import jakarta.servlet.annotation.*;
import javax.naming.InitialContext;
import javax.naming.NamingException;
#WebServlet(name = "helloServlet", value = "/hello", loadOnStartup = 1)
public class HelloServlet extends HttpServlet {
private String message;
#Resource(name= "java:comp/env/bean/Something")
private Something something;
#PostConstruct
public void doSomething(){
System.out.println("Does it work?");
}
public void init() {
message = "Hello World!";
try {
InitialContext ctx = new InitialContext();
Something lookup = (Something) ctx.lookup("java:comp/env/bean/Something");
System.out.println(lookup);
System.out.println(something); // null
} catch (NamingException e) {
e.printStackTrace();
}
}
public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException {
response.setContentType("text/html");
// Hello
PrintWriter out = response.getWriter();
out.println("<html><body>");
out.println("<h1>" + message + "</h1>");
out.println("</body></html>");
}
public void destroy() {
}
}
To reproduce the same issue, I created a sample repo here: https://github.com/sura-boy-playground/play-with-tomcat10
(Complete code can be found there)
At first, I had used javax.annotation.Resource annotation, so I thought that was the reason because of the javax.* to jakarta.* namespace change. Then I tried it with jakarta.annotation.Resource but the result was same.
I tried the same application with Tomcat 9.0.41 plus javax.* namespace, it works perfectly.
Is there any extra stuff that I need to do on Tomcat 10.0.10 to enable these annotations? I dug the Tomcat 10 documentation but I wasn't able to find out any thing related to my issue.
I found out that there was a similar case in Tomcat 7 previously, but I don't like that kind of workaround now.
Tomcat #Resource annotations API annotation stops working in Tomcat 7
You should declare the scope of your jakarta.annotation dependency as provided:
<dependency>
<groupId>jakarta.annotation</groupId>
<artifactId>jakarta.annotation-api</artifactId>
<version>2.0.0</version>
<scope>provided</scope>
</dependency>
If you have two copies of jakarta.annotation.Resource (one in the common classloader and one in your application's classloader), the two classes are different. The InstanceManager will look for fields annotated with the common classloader's copy of #Resource, while the something field is annotated with your webapp's copy of #Resource.
Edit: this problem was fixed in Tomcat 10.0.17 (cf. changelog), 9.0.59 and 10.1.0-M11.
Remark: You will have the same problem in Tomcat 9.0 if you use Java 11 or later. Before Java 11 the javax.annotation.* classes where included in the JRE. Servlet containers are required to look in the bootstrap/JRE classloader before looking in the webapp classloader (overriding javax.* classes is a breach of Java's licence), therefore Tomcat would never find the additional copy of the classes.

Spring Boot data-rest Jakson JSONSerializer empty

I've a Spring Boot project 1.3.3-Release that I've deployed on to a Web Logic 12c App Server. This code works fine on the embedded tomcat but not when I deploy on to Web Logic.
I've a Spring Data-Rest Repo
#RepositoryRestResource(collectionResourceRel = "car", path = "car")
public interface CarRepo extends PagingAndSortingRepository<Meter, Long>
{
List<Car> findall();
}
My Car POJO
#Table(name="car")
#Entity
public class Car
{
#Id
#Column(name="ID")
private Long id;
#Column(name="manufacturer")
private String manufacturer;
.......
}
Everything starts up and the web page loads and when I make the rest call I can see the from SQL output the SQL Query executing fine but I then get the below error in my server logs:
java.lang.AbstractMethodError: com.fasterxml.jackson.databind.JsonSerializer.isEmpty(Ljava/lang/Object;) at com.fasterxml.jackson.databind.ser.BeanPropertyWriter.serializeAsField(BeanPropertyWriter.java:528)
I'm assuming the data-rest is trying to automatically map the JSON Response from the endpoint into the Car object but it's failing for some unknown reason.
I've seen from the below link that there was a problem with Spring-Hateoas which I know spring-data-rest uses but seems as I'm using the latest version of spring-data-rest this shouldn't be a problem.
spring-hateoas error
Any help would be greatly appreciated
This looks like a version mismatch issue with JsonSerializer class. I think your weblogic classloader is loading an older version of com.fasterxml.jackson.core:jackson-databind, where the class JsonSerializer doesn't have the isEmpty Method.
From the docs :
/**
* Method called to check whether given serializable value is
* considered "empty" value (for purposes of suppressing serialization
* of empty values).
*<p>
* Default implementation will consider only null values to be empty.
*
* #since 2.0
*/
public boolean isEmpty(T value) {
return (value == null);
}
Ok so the solution is I had to tell weblogic specifically in the weblogic.xml to load the com.fasterxml.jackson packages from the application and not from it's own container.
<wls:package-name>com.fasterxml.jackson.*</wls:package-name>
Full weblogic.xml below:
<?xml version="1.0" encoding="UTF-8"?>
<wls:weblogic-web-app xmlns:wls="http://xmlns.oracle.com/weblogic/weblogic-web-app"
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/web-app_3_0.xsd
http://xmlns.oracle.com/weblogic/weblogic-web-app
http://xmlns.oracle.com/weblogic/weblogic-web-app/1.4/weblogic-web-app.xsd">
<wls:weblogic-version>12.2.1</wls:weblogic-version>
<wls:context-root>/ws/car</wls:context-root>
<wls:container-descriptor>
<wls:prefer-application-packages>
<wls:package-name>org.slf4j.*</wls:package-name>
<wls:package-name>javax.persistence.*</wls:package-name>
<wls:package-name>org.springframework.*</wls:package-name>
<wls:package-name>com.fasterxml.jackson.*</wls:package-name>
</wls:prefer-application-packages>
</wls:container-descriptor> </wls:weblogic-web-app>
Hope this helps others.

How do I define only scheduler attributes in the deployment descriptor, not the whole bean?

I have the following bean:
#Stateless
public class NewSessionBean {
public void myJob() {
System.out.println("RUN");
}
}
and I would like to have myJob running every 10 seconds, so I have this Deployment descriptor:
<ejb-jar xmlns = "http://java.sun.com/xml/ns/javaee"
version = "3.1"
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/ejb-jar_3_1.xsd">
<enterprise-beans>
<session>
<ejb-name>NewSessionBean</ejb-name>
<ejb-class>org.test.NewSessionBean</ejb-class>
<session-type>Stateless</session-type>
<timer>
<schedule>
<second>*/10</second>
<minute>*</minute>
<hour>*</hour>
<month>*</month>
<year>*</year>
</schedule>
<timeout-method>
<method-name>myJob</method-name>
</timeout-method>
</timer>
</session>
</enterprise-beans>
</ejb-jar>
And it works.
But I would like to declare only the timer in my deployment descriptor, not the whole bean so I can declare everything using annotations and parametrize the schedule.
If I remove the ejb-class or session-type my application won't load because the DD is missing this information.
Is there anyway that I can override the information for the scheduler only?
Edit: I would like to move set the parameters on the #schedule annotation to the deployment descriptor so I can change its values without needing to recompile/redeploy anything.

Weblogic Bea 10.0 M1 and WorkManager

I have to execute long running threads in a WebLogic Bea 10.0 M1 server environment. I tried to use WorkManagers for this. Using an own WorkManager allows me to specify my own thread timeout (MaxThreadStuckTime) instead of adjusting the timeout for the whole business application.
My setup is as follows:
weblogic-ejb-jar.xml:
<?xml version="1.0" encoding="UTF-8"?>
<weblogic-ejb-jar xmlns="http://www.bea.com/ns/weblogic/90" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.bea.com/ns/weblogic/90 http://www.bea.com/ns/weblogic/90/weblogic-ejb-jar.xsd">
<weblogic-enterprise-bean>
<ejb-name>TestBean</ejb-name>
<resource-description>
<res-ref-name>myWorkManager</res-ref-name>
<jndi-name>wm/myWorkManager</jndi-name>
</resource-description>
</weblogic-enterprise-bean>
</weblogic-ejb-jar>
weblogic-application.xml:
<?xml version="1.0" encoding="UTF-8"?>
<weblogic xmlns="http://www.bea.com/ns/weblogic/90" xmlns:j2ee="http://java.sun.com/xml/ns/j2ee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.bea.com/ns/weblogic/90
http://www.bea.com/ns/weblogic/90/weblogic.xsd">
<work-manager>
<name>myWorkManager</name>
<ignore-stuck-threads>1</ignore-stuck-threads>
</work-manager>
</weblogic>
and the Bean:
import javax.annotation.Resource;
import javax.ejb.Stateful;
import weblogic.work.WorkManager;
#Stateful(mappedName = "TestBean")
public class TestBean implements TestBeanRemote {
#Resource(name = "myWorkManager")
private WorkManager myWorkManager;
public void test() {
myWorkManager.schedule(new Runnable() {
public void run() {
while (true) {
System.out.println("test: +++++++++++++++++++++++++");
try {
Thread.sleep(45000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
});
}
}
When I try to deploy this things, the server gives me the following exceptions:
[EJB:011026]The EJB container failed while creating the java:/comp/env namespace for this EJB deployment.
weblogic.deployment.EnvironmentException: [EJB:010176]The resource-env-ref 'myWorkManager' declared in the ejb-jar.xml descriptor has no JNDI name mapped to it. The resource-ref must be mapped to a JNDI name using the resource-description element of the weblogic-ejb-jar.xml descriptor.
I try to figure out how to access / use WorkMangers for days now, and still get this or that as an exception. Very frustrating!
Thanks in advance!
You need to remove the WorkManager refrence from your weblogic-ejb-jar.xml, this refenece should go to ejb-jar.xml.
Infact I doubt if Weblogic schema definition "weblogic-ejb-jar.xsd" will allow you to add a reference element, you must be getting xsd validation errors.
anyways, get rid of the element
resource-description from weblogic-ejb-jar.xml
<weblogic-enterprise-bean>
<ejb-name>TestBean</ejb-name>
<resource-description>
<res-ref-name>myWorkManager</res-ref-name>
<jndi-name>wm/myWorkManager</jndi-name>
</resource-description>
</weblogic-enterprise-bean>
it will look like this
weblogic-ejb-jar.xml
<weblogic-enterprise-bean>
<ejb-name>TestBean</ejb-name>
</weblogic-enterprise-bean>
your workManager reference will go to ejb-jar.xml like this.
ejb-jar.xml
<enterprise-beans>
<session>
<ejb-name>TestBean</ejb-name>
<ejb-class>com.xxx.TestBean</ejb-class> <!-- your package com.xxx-->
<resource-ref>
<res-ref-name>myWorkManager</res-ref-name>
<res-type>commonj.work.WorkManager</res-type>
<res-auth>Container</res-auth>
</resource-ref>
</session>
</enterprise-beans>
Now to get WorkManager from JNDI I'm doing
InitialContext ctx = new InitialContext();
this.workManager = (WorkManager) ctx.lookup("java:comp/env/myWorkManager");
but I belive annotation will work equally well.
#Resource(name = "myWorkManager")
my weblogic-application.xml looks same as shared above
<weblogic>
<work-manager>
<name>myWorkManager</name>
<ignore-stuck-threads>1</ignore-stuck-threads>
</work-manager>
This is working for me .. let me know if needed I can share my full code.
you can view your WorkManager and load on it by going to Weblogic Admin Console
Home—>Deployments—>yourApp—>Monitoring(Tab)—>WorkLoad(Tab)”
You need to name your work manager. The way we do it is in our Ear project EarContent/META-INF/weblogic-application.xml
<wls:work-manager>
<wls:name>wmBatch</wls:name>
<wls:ignore-stuck-threads>true</wls:ignore-stuck-threads>
</wls:work-manager>
(which you appear to have done)
and then we use the annotations to set the manager:
#MessageDriven(ejbName =..., dispatchPolicy = "wmBatch")
And then there is no coding around getting the work manager. This might work for you.
BEA (together with IBM) have developed a framework specifically for managing long-running tasks in a Java EE environment. Take a look at CommonJ.
The Spring Framework offers some convenience classes around this framework.

Categories