BingAds / BingAds-Java-SDK

Other
43 stars 47 forks source link

ConcurrentModificationException in ReportingServiceManager#downloadFileAsync #164

Open markusheiden opened 1 year ago

markusheiden commented 1 year ago

Recently we got a ConcurrentModificationException in the ReportingServiceManager.

IMO that cannot be caused by our code, because we use a new ReportingServiceManager each time.

Maybe there is a problem in JAXB or CXF. Currently, we are using org.glassfish.jaxb 4.0.3 and org.apache.cxf 4.0.2.

Or the ReportingServiceManager has a concurrency issue.

Our code:

new ReportingServiceManager(authorizationData, environment)
    .downloadFileAsync(parameters, null)
    .get(10, MINUTES);

Stacktrace:

java.util.ConcurrentModificationException: null
    at java.util.HashMap.computeIfAbsent
    at org.glassfish.jaxb.runtime.v2.model.impl.TypeInfoSetImpl.getXmlNs(TypeInfoSetImpl.java:298)
    at org.glassfish.jaxb.runtime.v2.schemagen.XmlSchemaGenerator$Namespace.writeTo(XmlSchemaGenerator.java:565)
    at org.glassfish.jaxb.runtime.v2.schemagen.XmlSchemaGenerator.write(XmlSchemaGenerator.java:415)
    at org.glassfish.jaxb.runtime.v2.runtime.JAXBContextImpl.generateSchema(JAXBContextImpl.java:770)
    at org.apache.cxf.common.jaxb.JAXBUtils.generateJaxbSchemas(JAXBUtils.java:810)
    at org.apache.cxf.jaxb.JAXBDataBinding.generateJaxbSchemas(JAXBDataBinding.java:474)
    at org.apache.cxf.jaxb.JAXBDataBinding.initialize(JAXBDataBinding.java:391)
    at org.apache.cxf.service.factory.AbstractServiceFactoryBean.initializeDataBindings(AbstractServiceFactoryBean.java:87)
    at org.apache.cxf.wsdl.service.factory.ReflectionServiceFactoryBean.buildServiceFromClass(ReflectionServiceFactoryBean.java:469)
    at org.apache.cxf.jaxws.support.JaxWsServiceFactoryBean.buildServiceFromClass(JaxWsServiceFactoryBean.java:693)
    at org.apache.cxf.wsdl.service.factory.ReflectionServiceFactoryBean.initializeServiceModel(ReflectionServiceFactoryBean.java:529)
    at org.apache.cxf.wsdl.service.factory.ReflectionServiceFactoryBean.create(ReflectionServiceFactoryBean.java:262)
    at org.apache.cxf.jaxws.support.JaxWsServiceFactoryBean.create(JaxWsServiceFactoryBean.java:199)
    at org.apache.cxf.jaxws.ServiceImpl.createPort(ServiceImpl.java:466)
    at org.apache.cxf.jaxws.ServiceImpl.getPort(ServiceImpl.java:342)
    at org.apache.cxf.jaxws.ServiceImpl.getPort(ServiceImpl.java:337)
    at jakarta.xml.ws.Service.getPort(Service.java:210)
    at com.microsoft.bingads.internal.ServiceFactoryImpl.createProxyFromService(ServiceFactoryImpl.java:179)
    at com.microsoft.bingads.ServiceClient.getService(ServiceClient.java:159)
    at com.microsoft.bingads.v13.reporting.ReportingServiceManager.submitDownloadAsync(ReportingServiceManager.java:223)
    at com.microsoft.bingads.v13.reporting.ReportingServiceManager.downloadFileAsyncImpl(ReportingServiceManager.java:153)
    at com.microsoft.bingads.v13.reporting.ReportingServiceManager.downloadFileAsync(ReportingServiceManager.java:145)
    ...
qitia commented 1 year ago

hi, thanks for reaching out.

May I know what is the repro rate of the issue from your side?

Seems to me create a new ReportServiceManager instance for each call is not a good practice. Did you try reuse a single ReportServiceManager?

markusheiden commented 1 year ago

I just got this error once.

I will try to reuse the ReportingServiceManager as much as possible. We are using different accounts, so reuse is not always possible.

markusheiden commented 1 year ago

Another one, this time in the BulkServiceManager:

java.util.ConcurrentModificationException: null
    at java.util.HashMap.computeIfAbsent
    at org.glassfish.jaxb.runtime.v2.model.impl.TypeInfoSetImpl.getXmlNs(TypeInfoSetImpl.java:298)
    at org.glassfish.jaxb.runtime.v2.schemagen.XmlSchemaGenerator$Namespace.writeTo(XmlSchemaGenerator.java:565)
    at org.glassfish.jaxb.runtime.v2.schemagen.XmlSchemaGenerator.write(XmlSchemaGenerator.java:415)
    at org.glassfish.jaxb.runtime.v2.runtime.JAXBContextImpl.generateSchema(JAXBContextImpl.java:770)
    at org.apache.cxf.common.jaxb.JAXBUtils.generateJaxbSchemas(JAXBUtils.java:810)
    at org.apache.cxf.jaxb.JAXBDataBinding.generateJaxbSchemas(JAXBDataBinding.java:474)
    at org.apache.cxf.jaxb.JAXBDataBinding.initialize(JAXBDataBinding.java:391)
    at org.apache.cxf.service.factory.AbstractServiceFactoryBean.initializeDataBindings(AbstractServiceFactoryBean.java:87)
    at org.apache.cxf.wsdl.service.factory.ReflectionServiceFactoryBean.buildServiceFromClass(ReflectionServiceFactoryBean.java:469)
    at org.apache.cxf.jaxws.support.JaxWsServiceFactoryBean.buildServiceFromClass(JaxWsServiceFactoryBean.java:693)
    at org.apache.cxf.wsdl.service.factory.ReflectionServiceFactoryBean.initializeServiceModel(ReflectionServiceFactoryBean.java:529)
    at org.apache.cxf.wsdl.service.factory.ReflectionServiceFactoryBean.create(ReflectionServiceFactoryBean.java:262)
    at org.apache.cxf.jaxws.support.JaxWsServiceFactoryBean.create(JaxWsServiceFactoryBean.java:199)
    at org.apache.cxf.jaxws.ServiceImpl.createPort(ServiceImpl.java:466)
    at org.apache.cxf.jaxws.ServiceImpl.getPort(ServiceImpl.java:342)
    at org.apache.cxf.jaxws.ServiceImpl.getPort(ServiceImpl.java:337)
    at jakarta.xml.ws.Service.getPort(Service.java:210)
    at com.microsoft.bingads.internal.ServiceFactoryImpl.createProxyFromService(ServiceFactoryImpl.java:179)
    at com.microsoft.bingads.ServiceClient.getService(ServiceClient.java:159)
    at com.microsoft.bingads.v13.bulk.BulkServiceManager.submitDownloadAsync(BulkServiceManager.java:559)
    at com.microsoft.bingads.v13.bulk.BulkServiceManager.downloadFileAsyncImpl(BulkServiceManager.java:484)
    at com.microsoft.bingads.v13.bulk.BulkServiceManager.downloadEntitiesAsyncImpl(BulkServiceManager.java:435)
    at com.microsoft.bingads.v13.bulk.BulkServiceManager.downloadEntitiesAsync(BulkServiceManager.java:163)
markusheiden commented 8 months ago

For me this looks like a concurrency issue in the service managers: jakarta.xml.ws.Service and its implementation are not marked explicitly as thread-safe. So the com.microsoft.bingads.ServiceClient that wraps this class, may not be used from different threads. This seems to not play well with the asynchronous methods in the service managers.

The only suspicious location I found, was the com.microsoft.bingads.internal.ServiceFactoryImpl that creates a new jakarta.xml.ws.Service using a thread pool. Though it shuts down the thread pool immediately after the creation it does not wait for the shutdown to complete.

I provided #174 to fix this issue.