All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.microsoft.bingads.internal.ServiceFactoryImpl Maven / Gradle / Ivy

Go to download

The Bing Ads Java SDK is a library improving developer experience when working with the Bing Ads services by providing high-level access to features such as Bulk API, OAuth Authorization and SOAP API.

There is a newer version: 13.0.22.1
Show newest version
package com.microsoft.bingads.internal;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import java.util.logging.Level;
import java.util.logging.Logger;

import javax.xml.namespace.QName;

import com.microsoft.bingads.ApiEnvironment;
import com.microsoft.bingads.InternalException;

import jakarta.jws.WebService;
import jakarta.xml.ws.BindingProvider;
import jakarta.xml.ws.Service;
import jakarta.xml.ws.handler.MessageContext;
import jakarta.xml.ws.spi.Provider;

public class ServiceFactoryImpl implements ServiceFactory {

    private static final String VERSION = "13.0.16.2";
    
    private static final int DEFAULT_WS_CREATE_TIMEOUT_IN_SECOND = 60;
    
    private static final int WS_CREATE_RETRY_INTERVAL_IN_SECOND = 5;
    
    private static final int WS_CREATE_RETRY_TIMES = 3;

    private static Logger logger = Logger.getLogger(ServiceFactoryImpl.class.getName());

    private static final Map endpoints = new HashMap() {
        {

            put(com.microsoft.bingads.v13.customerbilling.ICustomerBillingService.class, new ServiceInfo() {
                {
                    setProductionUrl("https://clientcenter.api.bingads.microsoft.com/Api/Billing/v13/CustomerBillingService.svc");
                    setSandboxUrl("https://clientcenter.api.sandbox.bingads.microsoft.com/Api/Billing/v13/CustomerBillingService.svc");
                }
            });

            put(com.microsoft.bingads.v13.customermanagement.ICustomerManagementService.class, new ServiceInfo() {
                {
                    setProductionUrl("https://clientcenter.api.bingads.microsoft.com/Api/CustomerManagement/v13/CustomerManagementService.svc");
                    setSandboxUrl("https://clientcenter.api.sandbox.bingads.microsoft.com/Api/CustomerManagement/v13/CustomerManagementService.svc");
                }
            });

            put(com.microsoft.bingads.v13.reporting.IReportingService.class, new ServiceInfo() {
                {
                	setProductionUrl("https://reporting.api.bingads.microsoft.com/Api/Advertiser/Reporting/v13/ReportingService.svc");
                    setSandboxUrl("https://reporting.api.sandbox.bingads.microsoft.com/Api/Advertiser/Reporting/v13/ReportingService.svc");
                }
            });
            put(com.microsoft.bingads.v13.campaignmanagement.ICampaignManagementService.class, new ServiceInfo() {
                {
                    setProductionUrl("https://campaign.api.bingads.microsoft.com/Api/Advertiser/CampaignManagement/v13/CampaignManagementService.svc");
                    setSandboxUrl("https://campaign.api.sandbox.bingads.microsoft.com/Api/Advertiser/CampaignManagement/v13/CampaignManagementService.svc");
                }
            });
            put(com.microsoft.bingads.v13.adinsight.IAdInsightService.class, new ServiceInfo() {
                {
                    setProductionUrl("https://adinsight.api.bingads.microsoft.com/Api/Advertiser/AdInsight/v13/AdInsightService.svc");
                    setSandboxUrl("https://adinsight.api.sandbox.bingads.microsoft.com/Api/Advertiser/AdInsight/v13/AdInsightService.svc");
                }
            });
            put(com.microsoft.bingads.v13.bulk.IBulkService.class, new ServiceInfo() {
                {
                    setProductionUrl("https://bulk.api.bingads.microsoft.com/Api/Advertiser/CampaignManagement/v13/BulkService.svc");
                    setSandboxUrl("https://bulk.api.sandbox.bingads.microsoft.com/Api/Advertiser/CampaignManagement/v13/BulkService.svc");
                }
            });
			//End of v13
        }
    };

    @Override
    public Service createService(Class serviceInterface, ApiEnvironment env)
    {
        try {
            return createServiceWithRetry(serviceInterface, env);
        } catch (Exception e) {
            e.printStackTrace();
            throw new InternalException(e);
        }
    }

    // per #863657, Service.Create sometimes get hang. We implement timeout and retry for it.
    private Service createServiceWithRetry(Class serviceInterface, ApiEnvironment env) throws Exception {
        final QName qName = getServiceQname(serviceInterface);
        final boolean isCxf = Provider.provider().getClass().getName().contains("org.apache.cxf");
        final URL url = (isCxf ? null : new URL(getServiceUrl(serviceInterface, env) + "?wsdl")); 

        int retryLeft = WS_CREATE_RETRY_TIMES;
        int timeout = 0;
        ExecutorService pool = Executors.newSingleThreadExecutor();

        try {
            while (retryLeft > 0) {
                retryLeft--;
                timeout = prolongTimeout(timeout);
                Future future = pool.submit(new Callable() {
                    public Service call() throws Exception {
                        if (isCxf) {
                            // CXF doesn't require WSDL url to be passed
                            return Service.create(qName);
                        } else {
                            return Service.create(url, qName);
                        }
                    }
                });

                try {
                    return future.get(timeout, TimeUnit.SECONDS);
                } catch (TimeoutException e) {
                    System.out.println(String.format("Timeout. Failed to create web service %s in %d seconds for %s. retry left %d",
                            serviceInterface.getName(), timeout, env.value(), retryLeft));
                    future.cancel(true);

                    try {
                        if (retryLeft > 0) {
                            Thread.sleep(WS_CREATE_RETRY_INTERVAL_IN_SECOND * 1000);
                        }
                    } catch (InterruptedException e1) {
                        e1.printStackTrace();
                    }
                }
            }
        } finally {
            pool.shutdown();
        }
        throw new Exception(String.format("Failed to create Service %s for %s!", serviceInterface.getName(), env.value()));
    }

    private int prolongTimeout(int timeout) {
        return timeout + DEFAULT_WS_CREATE_TIMEOUT_IN_SECOND;
    }

    private String getServiceUrl(Class serviceInterface, ApiEnvironment env) {
        String serviceUrl = getServiceUrlFromConfig(serviceInterface);

        if (serviceUrl == null) {
            ServiceInfo serviceInfo = endpoints.get(serviceInterface);

            serviceUrl = serviceInfo.GetUrl(env);
        }

        return serviceUrl;
    }

    private QName getServiceQname(Class serviceInterface) {
        WebService webServiceAnnotation = (WebService) serviceInterface.getAnnotation(WebService.class);

        String serviceName = webServiceAnnotation.name();
        if (serviceName.startsWith("I")) {
            serviceName = serviceName.substring(1);
        }

        QName qName = new QName(webServiceAnnotation.targetNamespace(), serviceName);

        return qName;
    }

    @Override
    public  T createProxyFromService(Service service, ApiEnvironment env, Class serviceInterface) {
        T port = service.getPort(serviceInterface);
        String serviceUrl = getServiceUrl(serviceInterface, env);
        ((BindingProvider) port).getRequestContext().put(BindingProvider.ENDPOINT_ADDRESS_PROPERTY, serviceUrl);
        configServiceProxy(port);
        addUserAgent(port);

        return port;
    }

    /**
     * Inherited class could set timeout properties by override this method.
     * @param port Proxy supports Service T
     */
    protected  void configServiceProxy(T port) {
        // By default nothing is add here.
    }

    private String getServiceUrlFromConfig(Class serviceInterface) {
        InputStream input = null;
        try {
            File file = new File(ServiceUtils.getPropertyFile());
            if (!file.exists()) {
                return null;
            }
            input = new FileInputStream(file);
            Properties props = new Properties();
            props.load(input);
            return props.getProperty(serviceInterface.getCanonicalName() + ".url");
        } catch (IOException ex) {
            // Ignore. In this case we will load service Url from endpoints.
            return null;
        } finally {
            try {
                if (input != null) {
                    input.close();
                }
            } catch (IOException ex) {
                logger.log(Level.SEVERE, null, ex);
            }
        }
    }

    private  void addUserAgent(T port) {
        Map headers = new HashMap();
        
        String userAgent = "BingAdsSDKJava " + VERSION;

        String javaVersion = System.getProperty("java.version");
        if (javaVersion.matches("\\d+[\\d|\\.|\\_]*\\d+")) {
            // matches to 1.8.0_222, 11.0.2 and so on
            userAgent += " " + javaVersion;
        }
        headers.put("User-Agent", Arrays.asList(userAgent));

        ((BindingProvider) port).getRequestContext().put(MessageContext.HTTP_REQUEST_HEADERS, headers);
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy