2
votes

I am developing an application with SpringBoot 1.4.1 as the main framework. The app is a Maven Dynamic Web Project that exposes some web services and connects to various databases. It holds both servers and clients to connect with some other programs like Microsoft Dynamics or AutoCad.

It works as a "walkway" between some applications and some databases.

Web services are developed with CXF 3.1.8 and database access is done with Spring JPA for CRUD methods and MyBatis for complex queries.

Everything is configured through java clases and java beans (no xml config files used).

The app works fine both in spring boot embedded Tomcat (deploying it as spring boot app) and in WebLogic 12c server (deployed as a maven-build war).

But I have a strange behaviour with some of the web services methods. Specifically all methods work fine except for delete methods.

Here's a little part of the code.

I have a java parent class that implements methods that will be shared by web services. Then I have 2 or more java classes that extend this parent class and call super.method().

Here the parent class:

@Transactional(propagation = Propagation.SUPPORTS, rollbackFor = Exception.class)
public class FooService extends ServiceConfigurator {

    @Autowired
    protected FooRepository fooRepository;
    @Autowired
    protected FooMapper fooMapper;
    @Autowired
    protected FooFacade fooFacade;

    public ServiceResult persistFoo(final Foo foo) {
        this.getServiceResult();
        try {
            Foo result = this.fooFacade.persistFoo(foo, this.serviceResult);
            if (CollectionUtils.isEmpty(this.serviceResult.getErrors())) {
                result = this.fooMapper.findOne(result.getId());
                this.serviceResult.getResults().add(result);
                this.serviceResult.setSuccess(true);
            }
        } catch (final Exception e) {
            logger.error("ERROR", e);
            this.serviceResult.getErrors().addAll(Utils.addErrors(e));
            e.printStackTrace();
        }
        return this.serviceResult;
    }

    public ServiceResult deleteFoo(final Foo foo) {
        this.getServiceResult();
        try {
            final Helper helper = this.fooMapper.findById(helper.getId());
            final Foo existing = this.fooMapper.find(helper.getId(),     foo.getNumber(), foo.getVersion());
            this.fooFacade.deleteFoo(existing, this.serviceResult);
            if (CollectionUtils.isEmpty(this.serviceResult.getErrors())) {
                this.serviceResult.setSuccess(true);
            }
        } catch (final Exception e) {
            logger.error("ERROR", e);
            this.serviceResult.getErrors().addAll(Utils.addErrors(e));
            e.printStackTrace();
        }
        return this.serviceResult;
    }
}

And here one of the child classes:

@Service("fooImpService ")
@WebService(serviceName = "FooImpService ")
public class FooImpService extends FooService {

    public ServiceResult createFoo(@WebParam(name = "foo") final Foo foo) {
        return super.persistFoo(foo);
    }

This method above is working fine wherever I deploy my app, and so does this other (as example):

@Transactional(readOnly = false)
public ServiceResult findId(@WebParam(name = "idOne") final String idOne, @WebParam(name = "idTwo") final String idTwo,
        @WebParam(name = "version") final String version) {
    this.getServiceResult();
    try {
        final Foo foo = this.fooMapper.findById(idOne);
        final Fooresult = this.fooMapper.findByVersion(foo.getId(), idTwo, version);
        if (result != null) {
            this.serviceResult.getResults().add(result.getId());
            this.serviceResult.setSuccess(true);
        }
    } catch (final Exception e) {
        logger.error("ERROR", e);
        this.serviceResult.getErrors().addAll(Utils.addErrors(e));
        e.printStackTrace();
    }
    return this.serviceResult;
}

These methods work both as spring boot app, jar file o war file deployed in WebLogic.

But then, this method:

public ServiceResult deleteFoo(@WebParam(name = "foo") final Foo foo) {
    return super.deleteFoo(foo);
}

works fine in embedded Tomcat if I deploy the app as spring boot app, but when I try to deploy war to WebLogic I get the following exception:

Caused by: java.lang.NullPointerException:
    at com.sun.xml.ws.spi.db.JAXBWrapperAccessor.getPropertyAccessor(JAXBWrapperAccessor.java:261)
    at com.sun.xml.ws.db.toplink.JAXBContextWrapper.getElementPropertyAccessor(JAXBContextWrapper.java:170)
    at com.sun.xml.ws.server.sei.EndpointArgumentsBuilder$DocLit.<init>(EndpointArgumentsBuilder.java:598)
    at com.sun.xml.ws.server.sei.TieHandler.createArgumentsBuilder(TieHandler.java:143)
    at com.sun.xml.ws.server.sei.TieHandler.<init>(TieHandler.java:115)
    at com.sun.xml.ws.db.DatabindingImpl.<init>(DatabindingImpl.java:118)
    at com.sun.xml.ws.db.DatabindingProviderImpl.create(DatabindingProviderImpl.java:74)
    at com.sun.xml.ws.db.DatabindingProviderImpl.create(DatabindingProviderImpl.java:58)
    at com.sun.xml.ws.db.DatabindingFactoryImpl.createRuntime(DatabindingFactoryImpl.java:120)
    at com.sun.xml.ws.server.EndpointFactory.createSEIModel(EndpointFactory.java:521)
    at com.sun.xml.ws.server.EndpointFactory.create(EndpointFactory.java:300)
    at com.sun.xml.ws.server.EndpointFactory.createEndpoint(EndpointFactory.java:164)
    at com.sun.xml.ws.api.server.WSEndpoint.create(WSEndpoint.java:577)
    at com.sun.xml.ws.api.server.WSEndpoint.create(WSEndpoint.java:560)
    at com.sun.xml.ws.api.server.WSEndpoint.create(WSEndpoint.java:639)
    at weblogic.wsee.jaxws.JAXWSDeployedServlet.getEndpoint(JAXWSDeployedServlet.java:355)
    at weblogic.wsee.jaxws.JAXWSServlet.registerEndpoint(JAXWSServlet.java:167)
    at weblogic.wsee.jaxws.JAXWSServlet.init(JAXWSServlet.java:79)
    at weblogic.wsee.jaxws.JAXWSDeployedServlet.init(JAXWSDeployedServlet.java:91)
    at javax.servlet.GenericServlet.init(GenericServlet.java:244)
    at weblogic.servlet.internal.StubSecurityHelper$ServletInitAction.run(StubSecurityHelper.java:343)
    at weblogic.servlet.internal.StubSecurityHelper$ServletInitAction.run(StubSecurityHelper.java:294)
    at weblogic.security.acl.internal.AuthenticatedSubject.doAs(AuthenticatedSubject.java:326)
    at weblogic.security.service.SecurityManager.runAsForUserCode(SecurityManager.java:197)
    at weblogic.servlet.provider.WlsSecurityProvider.runAsForUserCode(WlsSecurityProvider.java:203)
    at weblogic.servlet.provider.WlsSubjectHandle.run(WlsSubjectHandle.java:71)
    at weblogic.servlet.internal.StubSecurityHelper.initServletInstance(StubSecurityHelper.java:99)
    at weblogic.servlet.internal.StubSecurityHelper.createServlet(StubSecurityHelper.java:87)
    at weblogic.servlet.internal.StubLifecycleHelper.createOneInstance(StubLifecycleHelper.java:71)
    at weblogic.servlet.internal.StubLifecycleHelper.<init>(StubLifecycleHelper.java:57)
    at weblogic.servlet.internal.StubLifecycleHelper.<init>(StubLifecycleHelper.java:31)
    at weblogic.servlet.internal.ServletStubImpl.initStubLifecycleHelper(ServletStubImpl.java:673)
    at weblogic.servlet.internal.ServletStubImpl.prepareServlet(ServletStubImpl.java:612)
    at weblogic.servlet.internal.WebAppServletContext.preloadServlet(WebAppServletContext.java:2054)
    at weblogic.servlet.internal.WebAppServletContext.loadServletsOnStartup(WebAppServletContext.java:2031)
    at weblogic.servlet.internal.WebAppServletContext.preloadResources(WebAppServletContext.java:1920)
    at weblogic.servlet.internal.WebAppServletContext.start(WebAppServletContext.java:3091)
    at weblogic.servlet.internal.WebAppModule.startContexts(WebAppModule.java:1823)
    at weblogic.servlet.internal.WebAppModule.start(WebAppModule.java:882)
    at weblogic.application.internal.ExtensibleModuleWrapper$StartStateChange.next(ExtensibleModuleWrapper.java:360)
    at weblogic.application.internal.ExtensibleModuleWrapper$StartStateChange.next(ExtensibleModuleWrapper.java:356)
    at weblogic.application.utils.StateMachineDriver.nextState(StateMachineDriver.java:45)
    at weblogic.application.internal.ExtensibleModuleWrapper.start(ExtensibleModuleWrapper.java:138)

This exception may be caused by something related to @WebParam annotation, because when I remove the annotation from delete method, the app is deployed correctly and method works fine in WebLogic.

1
I have a similar issue where spring boot my jar and war was working fine and WLS it didn't work where I was using JAXB and I came to know WLS uses its own JAXBMarshaller and I have added the package within META-INF and mapped to weblogic.xml using prefer-application-resources. I don't think it is same to your issue but check on this line also.user3428736
looks like class conflict as mentioned in above comment.ulab
@user3428736 What packages have you added to weblogic.xml? In my app I have jaxb-core and jaxb-impl jars, but I'm not sure what packages to add...Maybe com.sun.xml?DANIEL ALVAREZ
@DANIEL ALVAREZ add META-INF\services with a file named as com.sun.xml.ws.spi.db.BindingContextFactory and JAXBContext with your package as a file and add the location in your web-logic.xml as mentioned above.user3428736

1 Answers

0
votes

The following link https://axis.apache.org/axis2/java/core/docs/app_server.html is for Axis, but seems more generally applicable to custom wars on weblogic. It states

if you want to deploy custom WARs, say in a clustering environment, you need to add two additional files into the WEB-INF named "services.list" and "modules.list" under the modules and services directory respectively.

WEB-INF/services/services.list : should list all the services (aar files) that you want to expose. WEB-INF/modules/modules.list : should list all the modules (mar files) that you want to use.

NOTE: In both cases, please list one entry per line.

WebLogic ships with JARs that conflict with JARs present in Axis2. Therefore use to ensure that JARs packaged in Axis2 WAR are picked up from WEB-INF/lib. You can do this by setting the element in WEB-INF/weblogic.xml to true. An example of weblogic.xml is shown below:

<weblogic-web-app>
     <container-descriptor>
         <prefer-web-inf-classes>true</prefer-web-inf-classes>
     </container-descriptor>
</weblogic-web-app>

If set to true, the element will force WebLogic's classloader to load classes located in the WEB-INF directory of a Web application in preference to application or system classes. This is a recommended approach since it only impacts a single Web module.

For CXF, a similar document is at http://cxf.apache.org/docs/application-server-specific-configuration-guide.html#ApplicationServerSpecificConfigurationGuide-WebLogic :

Create a weblogic-application.xml (Weblogic specific) in the META-INF folder.

<?xml version="1.0" encoding="UTF-8"?>
<weblogic-application xmlns="http://www.bea.com/ns/weblogic/90">
    <application-param>
        <param-name>webapp.encoding.default</param-name>
        <param-value>UTF-8</param-value>
    </application-param>
    <prefer-application-packages>
        <package-name>javax.jws.*</package-name>
    </prefer-application-packages>
</weblogic-application>