"Повторяющееся имя файла" для того же пространства имен WSDL при использовании веб-службы из разных поддоменов
Предисловие
Мы предоставляем клиентам наш сервис API.
У каждого клиента есть собственный поддомен (например, sergii.ourwebsite.com) и собственный URL-адрес WSDL, он выглядит как http://sergii.ourwebsite.com/api/bsapi.cfc?wsdl
Также все сайты (включая API, конечно) используют одинаковую кодовую базу.
проблема
Скажем, два приложения на одном CF-сервере. Это может легко произойти, потому что некоторые из веб-сайтов клиентов размещены на наших серверах.
Оба пытаются использовать собственный API WSDL, говорят:
http://sergii.ourwebsite.com/api/bsapi.cfc?wsdl
http://galashyn.ourwebsite.com/api/bsapi.cfc?wsdl
И тут возникают проблемы.
Когда второй сайт пытается зарегистрировать веб-сервис, CF выдает ошибку:
Имя: https://galashyn.ourwebsite.com/api/bsapi.cfc?wsdl. WSDL: https://galashyn.ourwebsite.com/api/bsapi.cfc?wsdl. org.apache.axis.wsdl.toJava.DuplicateFileException: повторяющееся имя файла: /opt/coldfusion8/stubs/WS1985941973/api/Bsapi.java. Подсказка: возможно, вы сопоставили два пространства имен с элементами с одинаковым именем с одним и тем же именем пакета. Рекомендуется использовать веб-браузер для получения и проверки запрошенного документа WSDL, чтобы убедиться в его правильности. Если запрошенный документ WSDL не может быть получен или генерируется динамически, вероятно, что целевой веб-сервис имеет ошибки программирования.
Проблема в том, что они оба используют одно и то же пространство имен WSDL, построенное из пути CFC:
<wsdl:definitions targetNamespace="http://api">
Текущее решение
Единственное рабочее решение для нас - это использование псевдонимов CFC, например:
http://galashyn.ourwebsite.com/api/v1n1/bsapi.cfc?wsdl
http://galashyn.ourwebsite.com/api/v1n1/bsapi.cfc?wsdl
Каждый этот CFC расширяет родителя следующим образом:
<cfcomponent output="false" extends="api.bsapi">
<!--- this component used to extend base api version 1.x --->
</cfcomponent>
Они создают разные пространства имен, которые можно использовать без проблем - собственное пространство имен для каждого приложения:
<wsdl:definitions targetNamespace="http://v1n1.api">
<wsdl:definitions targetNamespace="http://v1n2.api">
Это довольно тупой обходной путь, но пока он работает.
Другое решение состоит в том, чтобы использовать один поддомен API и идентифицировать клиентов по некоторому ключу (мы уже используем их в целях безопасности), но у нас есть серьезные негативные проблемы из-за некоторого устаревшего кода.
Обратите внимание, что я не знаю Java, поэтому многие конкретные советы мне не так понятны.
Google показывает, что эта проблема существует годами, но я не могу найти разумное решение.
Так может здесь?
4 ответа
Сейчас я не могу "разместить WSDL на общем URL-адресе для всех клиентов", и я объяснил почему: потому что я должен использовать субдомены. Если вы знаете, как разместить WSDL на одном URL-адресе и отправлять запросы на обслуживание другому - скажите, пожалуйста.
WSDL - это просто документ XML, описывающий веб-сервис. Вы можете написать (настроить) его, используя CFML. Например:
http://subdomain.domain.com/api/wsdl.cfm?api=bsapi&customer=subdomain
Затем просто скопируйте WSDL, сгенерированный CF, и используйте его в качестве шаблона для своей пользовательской страницы WSDL. Замените части WSDL, которые зависят от субдомена, и верните XML-документ. Будьте внимательны к пробелам (возможно, смотрите CFSilent, CFSetting) и рассмотрите возможность использования CFHeader для установки типа mime на "text/xml".
Все ли клиенты используют один и тот же WSDL? Затем разместите WSDL по общему URL для всех клиентов.
Я также думаю, что вам нужно выяснить, что именно означает сообщение об ошибке. Я не вижу, какое отношение это имеет к используемому URL. Если бы он упомянул URL другого клиента, я бы понял.
Частично это может быть связано с моим непониманием того, как работает CF. В частности, что это за "регистрация веб-сервисов", которая вызывает проблему, когда это делают два клиента?
Вы поняли, что URL в <soap:address/>
элемент в WSDL это только подсказка? У многих клиентов это может быть переопределено. В клиенте.NET просто установите свойство Url прокси-класса. Это должно позволить вам иметь один WSDL в одном месте, и при этом ваши клиенты каждый должны ссылаться на соответствующий поддомен, при условии, что есть какой-то способ донести эту информацию до них. Например, если у вас есть способ узнать, какой клиент совершает вызов, то, возможно, вы могли бы получать вызовы по одному URL-адресу и затем перенаправлять на правильный URL-адрес или использовать инфраструктуру маршрутизации SOAP для маршрутизации на правильный.
Я надеюсь, что вы не меняете пространства имен от одного клиента к другому. Пространства имен не имеют ничего общего с URL, даже если они выглядят как URL.
Для тега cfcomponent есть атрибут пространства имен. Вы должны иметь возможность использовать это вместе с cgi.host_name (? Я дома, без документов), чтобы указать пространство имен, которое соответствует запрашиваемому поддомену.
Что-то вроде:
<cfcomponent namespace="http://#cgi.host_name#/api/v1n1/bsapi.cfc">
Это сообщение об ошибке при попытке выполнить веб-службу CFINVOKE с локального хоста с помощью тестового сценария, расположенного на том же локальном хосте (но в другой папке). Звучит как-то "багги" для меня.