Javax xml rpc soap soapfaultexception server error

Hi,

I have Dyn Pro application deployed on NW app server. The application uses webservices on PI and the whole process working until a month back. Recently the application stopped working an

Hi,

<P>

I have Dyn Pro application deployed on NW app server. The application uses webservices on PI and the whole process working until a month back. Recently the application stopped working and throwing following error. Also I use following code for Authentication.

<P>

<P>

I am not sure where the issue is? I looked at forums before posting and could not find anything. I wonder if any one ran into the issue and how is it fixed? I appreciate your help.

<P>

<P>

CODE

<P>

<P>

if ( port instanceof Stub ) {

final Stub stub = (Stub)port; stub._setProperty(Stub.USERNAME_PROPERTY, «abcd»);

stub._setProperty(Stub.PASSWORD_PROPERTY, «123»);

} else if (port instanceof DInterfaceInvoker) {

final DInterfaceInvoker invoker = (DInterfaceInvoker)port;

invoker.setProperty(Stub.USERNAME_PROPERTY, «abcd»);

invoker.setProperty(Stub.PASSWORD_PROPERTY, «123»);

}

<P>

}

<P>

Exception is:

<P>

<P>

java.lang.RuntimeException: com.sap.tc.webdynpro.model.webservice.api.WDWSModelExecuteException: Exception on execution of web service with WSDL URL ‘C:
cliqbook
wsdl
MI_Project_Search_Request_Response1.wsdl’ with operation ‘MI_Project_Search_Request_Response’ in interface ‘MI_Project_Search_Request_Response’ at com.app.freeman.search.cliqbook.CliqBookSearch.executeRequest_MI_Project_Search_Request_Response(CliqBookSearch.java:294) at com.app.freeman.search.cliqbook.wdp.InternalCliqBookSearch.executeRequest_MI_Project_Search_Request_Response(InternalCliqBookSearch.java:387) at com.app.freeman.search.cliqbook.CliqBookSearchView.onActionSearch(CliqBookSearchView.java:160) at com.app.freeman.search.cliqbook.wdp.InternalCliqBookSearchView.wdInvokeEventHandler(InternalCliqBookSearchView.java:380) at com.sap.tc.webdynpro.progmodel.generation.DelegatingView.invokeEventHandler(DelegatingView.java:87) at com.sap.tc.webdynpro.progmodel.controller.Action.fire(Action.java:67) at com.sap.tc.webdynpro.clientserver.window.WindowPhaseModel.doHandleActionEvent(WindowPhaseModel.java:420) at com.sap.tc.webdynpro.clientserver.window.WindowPhaseModel.processRequest(WindowPhaseModel.java:132) at com.sap.tc.webdynpro.clientserver.window.WebDynproWindow.processRequest(WebDynproWindow.java:335) at com.sap.tc.webdynpro.clientserver.cal.AbstractClient.executeTasks(AbstractClient.java:143) at com.sap.tc.webdynpro.clientserver.session.ApplicationSession.doProcessing(ApplicationSession.java:321) at com.sap.tc.webdynpro.clientserver.session.ClientSession.doApplicationProcessingStandalone(ClientSession.java:713) at com.sap.tc.webdynpro.clientserver.session.ClientSession.doApplicationProcessing(ClientSession.java:666) at com.sap.tc.webdynpro.clientserver.session.ClientSession.doProcessing(ClientSession.java:250) at com.sap.tc.webdynpro.clientserver.session.RequestManager.doProcessing(RequestManager.java:149) at com.sap.tc.webdynpro.serverimpl.defaultimpl.DispatcherServlet.doContent(DispatcherServlet.java:62) at com.sap.tc.webdynpro.serverimpl.defaultimpl.DispatcherServlet.doPost(DispatcherServlet.java:53) at javax.servlet.http.HttpServlet.service(HttpServlet.java:760) at javax.servlet.http.HttpServlet.service(HttpServlet.java:853) at com.sap.engine.services.servlets_jsp.server.HttpHandlerImpl.runServlet(HttpHandlerImpl.java:401) at com.sap.engine.services.servlets_jsp.server.HttpHandlerImpl.handleRequest(HttpHandlerImpl.java:266) at com.sap.engine.services.httpserver.server.RequestAnalizer.startServlet(RequestAnalizer.java:386) at com.sap.engine.services.httpserver.server.RequestAnalizer.startServlet(RequestAnalizer.java:364) at com.sap.engine.services.httpserver.server.RequestAnalizer.invokeWebContainer(RequestAnalizer.java:1039) at com.sap.engine.services.httpserver.server.RequestAnalizer.handle(RequestAnalizer.java:265) at com.sap.engine.services.httpserver.server.Client.handle(Client.java:95) at com.sap.engine.services.httpserver.server.Processor.request(Processor.java:175) at com.sap.engine.core.service630.context.cluster.session.ApplicationSessionMessageListener.process(ApplicationSessionMessageListener.java:33) at com.sap.engine.core.cluster.impl6.session.MessageRunner.run(MessageRunner.java:41) at com.sap.engine.core.thread.impl3.ActionObject.run(ActionObject.java:37) at java.security.AccessController.doPrivileged(Native Method) at com.sap.engine.core.thread.impl3.SingleThread.execute(SingleThread.java:104) at com.sap.engine.core.thread.impl3.SingleThread.run(SingleThread.java:176) Caused by: com.sap.tc.webdynpro.model.webservice.api.WDWSModelExecuteException: Exception on execution of web service with WSDL URL ‘C:
cliqbook
wsdl
MI_Project_Search_Request_Response1.wsdl’ with operation ‘MI_Project_Search_Request_Response’ in interface ‘MI_Project_Search_Request_Response’ … 33 more Caused by: java.lang.reflect.InvocationTargetException: Server Error at com.sap.engine.services.webservices.jaxrpc.wsdl2java.soapbinding.MimeHttpBinding.processDocumentFault(MimeHttpBinding.java:927) at com.sap.engine.services.webservices.jaxrpc.wsdl2java.soapbinding.MimeHttpBinding.call(MimeHttpBinding.java:1440) at MI_ProjectSearchRequestResponseBindingStub._invoke(MI_ProjectSearchRequestResponseBindingStub.java:99) at com.sap.engine.services.webservices.espbase.client.dynamic.impl.DInterfaceInvokerImpl.invokeOperation(DInterfaceInvokerImpl.java:63) at com.sap.tc.webdynpro.model.webservice.model.WSGenericModelClassExecutable.execute(WSGenericModelClassExecutable.java:68) at com.sap.tc.webdynpro.model.webservice.gci.WSTypedModelClassExecutable.execute(WSTypedModelClassExecutable.java:46) at com.app.freeman.search.cliqbook.CliqBookSearch.executeRequest_MI_Project_Search_Request_Response(CliqBookSearch.java:248) … 32 more Caused by: javax.xml.rpc.soap.SOAPFaultException: Server Error at com.sap.engine.services.webservices.jaxrpc.wsdl2java.soapbinding.MimeHttpBinding.buildFaultException(MimeHttpBinding.java:737) at com.sap.engine.services.webservices.jaxrpc.wsdl2java.soapbinding.MimeHttpBinding.processDocumentFault(MimeHttpBinding.java:860) …

<P>

Thank you,

Balaji


Offline

bearchik

 


#1
Оставлено
:

15 сентября 2017 г. 17:30:40(UTC)

bearchik

Статус: Новичок

Группы: Участники

Зарегистрирован: 08.09.2017(UTC)
Сообщений: 2

Собственно есть DSS поднятый полностью на сайте с гост алгоритмами. Пытаюсь подключится используя примеры — вываливается exception:

Цитата:

Exception in thread «main» javax.xml.ws.soap.SOAPFaultException: ID4184: The EncryptingCredentials provided in the SecurityTokenDescriptor must not be null if Scope.TokenEncryptionRequired is set to true. This can be caused by the Scope specifying an unsupported encryption key type, or by the incoming RequestSecurityToken message containing an unsupported EncryptionAlgorithm. Override CreateSecurityTokenDescriptor if you need to support algorithms other than AES 256.

Гугл, яндекс, дакдакго ничего не дал по этому поводу, куда копать уже не знаю.
CryptoPro JCP и TLS установлен и без проблем подключается к самому сайту, а вот насколько я понимаю SOAP запрос подписать не может.
Если переключаю на тестовый сайт dss.cryptopro.ru без гост шифрования(с обычными ssl) — все работает без проблем.
Код имеет следующий вид:

Код:

public class MainClass {

    public static void main(String[] args) {

        Security.setProperty("ssl.SocketFactory.provider", "ru.CryptoPro.ssl.SSLSocketFactoryImpl");

        System.setProperty("javax.net.ssl.keyStoreType", "HDImageStore");
        System.setProperty("javax.net.ssl.trustStoreType", "HDImageStore");
        System.setProperty("javax.net.ssl.trustStore", "E:\truststore.store");
        System.setProperty("javax.net.ssl.trustStorePassword", "password");
        System.setProperty("com.sun.security.enableCRLDP", "true");
        System.setProperty("com.ibm.security.enableCRLDP", "true");

        DefaultSTSIssuedTokenConfiguration stsConfig = new DefaultSTSIssuedTokenConfiguration(
                STSIssuedTokenConfiguration.PROTOCOL_13,
                "https://dss.testserver.test/STS/Active.svc/username/transport",
                "http://dss.testserver.test/STS/Active.svc/mex");


        stsConfig.getOtherOptions().put(BindingProvider.USERNAME_PROPERTY,"testuser");
        stsConfig.getOtherOptions().put(BindingProvider.PASSWORD_PROPERTY,"password");


        try {
            SignService srv = new SignService(new URL("http://dss.testserver.test/SignServer/SignService.svc?wsdl"));
            Iterator<QName> ports = srv.getPorts();
            ISignService client = null;
            while (ports.hasNext()) {
                QName portName = ports.next();
                ISignService p = srv.getPort(portName, ISignService.class, new WebServiceFeature[] {
                        new STSIssuedTokenFeature(stsConfig)
                });
                String en = (String)((BindingProvider)p).getRequestContext().get(BindingProvider.ENDPOINT_ADDRESS_PROPERTY);
                if(en.equals("https://dss.testserver.test/SignServer/SignServiceR.svc/issuedtoken/transport/nosc")) {
                    client = p;
                    break;
                }
            }

            if (client == null) {
                System.out.println("Cannot find endpoint in service WSDL");
            }

            ArrayOfDSSCertificate certs = client.getCertificates(); // здесь собственно падает в ошибку

        } catch (MalformedURLException e) {
            e.printStackTrace();
        } catch (ISignServiceGetCertificatesDssFaultFaultFaultMessage iSignServiceGetCertificatesDssFaultFaultFaultMessage) {
            iSignServiceGetCertificatesDssFaultFaultFaultMessage.printStackTrace();
        }
    }

}

Полный стек ошибки:

Цитата:

Exception in thread «main» javax.xml.ws.soap.SOAPFaultException: ID4184: The EncryptingCredentials provided in the SecurityTokenDescriptor must not be null if Scope.TokenEncryptionRequired is set to true. This can be caused by the Scope specifying an unsupported encryption key type, or by the incoming RequestSecurityToken message containing an unsupported EncryptionAlgorithm. Override CreateSecurityTokenDescriptor if you need to support algorithms other than AES 256.
at com.sun.xml.ws.fault.SOAP12Fault.getProtocolException(SOAP12Fault.java:229)
at com.sun.xml.ws.fault.SOAPFaultBuilder.createException(SOAPFaultBuilder.java:126)
at com.sun.xml.ws.client.dispatch.DispatchImpl.doInvoke(DispatchImpl.java:199)
at com.sun.xml.ws.client.dispatch.DispatchImpl.invoke(DispatchImpl.java:218)
at com.sun.xml.ws.security.trust.impl.TrustPluginImpl.invokeRST(TrustPluginImpl.java:628)
at com.sun.xml.ws.security.trust.impl.TrustPluginImpl.process(TrustPluginImpl.java:174)
at com.sun.xml.ws.security.trust.impl.client.STSIssuedTokenProviderImpl.getIssuedTokenContext(STSIssuedTokenProviderImpl.java:144)
at com.sun.xml.ws.security.trust.impl.client.STSIssuedTokenProviderImpl.issue(STSIssuedTokenProviderImpl.java:74)
at com.sun.xml.ws.api.security.trust.client.IssuedTokenManager.getIssuedToken(IssuedTokenManager.java:83)
at com.sun.xml.wss.jaxws.impl.SecurityClientTube.invokeTrustPlugin(SecurityClientTube.java:685)
at com.sun.xml.wss.jaxws.impl.SecurityClientTube.processClientRequestPacket(SecurityClientTube.java:281)
at com.sun.xml.wss.jaxws.impl.SecurityClientTube.processRequest(SecurityClientTube.java:247)
at com.sun.xml.ws.api.pipe.Fiber.__doRun(Fiber.java:641)
at com.sun.xml.ws.api.pipe.Fiber._doRun(Fiber.java:600)
at com.sun.xml.ws.api.pipe.Fiber.doRun(Fiber.java:585)
at com.sun.xml.ws.api.pipe.Fiber.runSync(Fiber.java:482)
at com.sun.xml.ws.client.Stub.process(Stub.java:323)
at com.sun.xml.ws.client.sei.SEIStub.doProcess(SEIStub.java:161)
at com.sun.xml.ws.client.sei.SyncMethodHandler.invoke(SyncMethodHandler.java:113)
at com.sun.xml.ws.client.sei.SyncMethodHandler.invoke(SyncMethodHandler.java:93)
at com.sun.xml.ws.client.sei.SEIStub.invoke(SEIStub.java:144)
at com.sun.proxy.$Proxy46.getCertificates(Unknown Source)
at MainClass.main(MainClass.java:80)


Вверх


Offline

khomenko

 


#2
Оставлено
:

19 сентября 2017 г. 12:14:54(UTC)

Михаил Хоменко

Статус: Активный участник

Группы: Администраторы, Участники
Зарегистрирован: 28.04.2010(UTC)
Сообщений: 140
Мужчина
Откуда: Крипто-Про

Поблагодарили: 15 раз в 14 постах

На данный момент DSS предоставляет более простой для интеграции интерфейс REST.
Рекомендуем использовать его.

Указанная ошибка приходит с Центра Идентификации DSS. Необходимо проверить его настройки:
убедиться что для проверяющей стороны «Сервиса Подписи» задан сертификат шифрования.
см. Рук-во разработчика командлеты *-DssRelyingPartyTrust


Вверх


Offline

bearchik

 


#3
Оставлено
:

19 сентября 2017 г. 17:20:37(UTC)

bearchik

Статус: Новичок

Группы: Участники

Зарегистрирован: 08.09.2017(UTC)
Сообщений: 2

Спасибо за ответ.

Сертификат шифрования был задан.
PS C:UsersAdministrator> Get-DssRelyingPartyTrust -DisplayName sts -Id 3


ID Свойства Статус


3 Отображаемое имя проверяющей стороны: SignServer Активна
Описание проверяющей стороны:
Шифрование маркера безопасности: Включено
Делегирование: Отключено
URL-адрес администрирования: Администрирование отключено
URL-адрес сервисного канала: https://dss.testserver.t…ce.svc/transactiontokens
Поддержка сервисного канала: Включена
Идентификаторы проверяющей стороны:
http://dss.testserver.te…gnService.svc/federation
http://dss.testserver.te…vice.svc/federation/nosc
http://dss.testserver.te…nService.svc/issuedtoken
http://dss.testserver.te…er/SignService.svc/token
http://dss.testserver.te…ceR.svc/issuedtoken/nosc
http://dss.testserver.te…nServiceR.svc/token/nosc
https://dss.testserver.test/SignServer/rest
https://dss.testserver.test/SignServer/rest/api
https://dss.testserver.t…svc/federation/transport
https://dss.testserver.t…ederation/transport/nosc
https://dss.testserver.t…vc/issuedtoken/transport
https://dss.testserver.t…suedtoken/transport/cert
https://dss.testserver.t…oken/transport/nosc/cert
https://dss.testserver.t…vice.svc/token/transport
https://dss.testserver.t…ce.svc/transactiontokens
https://dss.testserver.t…suedtoken/transport/nosc
https://dss.testserver.t…svc/token/transport/nosc


Сертификат шифрования маркера безопасности:


Параметр Значение


Субъект CN=dss.testserver.test


Издатель CN=dss.testserver.test


Отпечаток 8AB8F02F4B602BD6151CE980BE8382605F17C1B5


Срок действия 12.07.2018


Вверх


Offline

marrow

 


#4
Оставлено
:

25 сентября 2017 г. 10:40:03(UTC)

marrow

Статус: Активный участник

Группы: Участники

Зарегистрирован: 14.06.2016(UTC)
Сообщений: 56
Мужчина
Российская Федерация

Сказал «Спасибо»: 4 раз
Поблагодарили: 3 раз в 3 постах

День добрый.
Через интерфейс REST, необходимо для регистрации пользователя присвоить Client_ID. Пока не понимаю где получить Client_ID.
В документации написано, что допустимое значение данного параметра сохраняется в ЦИ на этапе регистрации клиента. Хочу сначала понять логику. Например сделали регистрацию клиента через Web-интерфейс, Client ID сейчас возможно посмотреть в ЦИ (например в БД), как он выглядит?


Вверх


Offline

khomenko

 


#5
Оставлено
:

25 сентября 2017 г. 14:55:57(UTC)

Михаил Хоменко

Статус: Активный участник

Группы: Администраторы, Участники
Зарегистрирован: 28.04.2010(UTC)
Сообщений: 140
Мужчина
Откуда: Крипто-Про

Поблагодарили: 15 раз в 14 постах

Добрый день,

Client_ID задаёт администратор. См. рук-во администратора, командлеты *-DssClient


Вверх


Offline

marrow

 


#6
Оставлено
:

26 сентября 2017 г. 12:23:26(UTC)

marrow

Статус: Активный участник

Группы: Участники

Зарегистрирован: 14.06.2016(UTC)
Сообщений: 56
Мужчина
Российская Федерация

Сказал «Спасибо»: 4 раз
Поблагодарили: 3 раз в 3 постах

Есть ли возможность узнать Client_ID от вашего тестового DSS (dss.cryptopro.ru) и сделать запрос?


Вверх


Offline

marrow

 


#7
Оставлено
:

27 сентября 2017 г. 9:58:56(UTC)

marrow

Статус: Активный участник

Группы: Участники

Зарегистрирован: 14.06.2016(UTC)
Сообщений: 56
Мужчина
Российская Федерация

Сказал «Спасибо»: 4 раз
Поблагодарили: 3 раз в 3 постах

Добрый день.

Хочу получить маркер доступа через интерфейс REST.

Выполняю запрос:
POST https://dss01.nucrf.ru/STS/oauth/token HTTP/1.1
Host: dss01.nucrf.ru
Accept: application/json
Content-Type: application/x-www-form-urlencoded
Authorization: Basic dXNlcjcwMDoxMjM0NQ==
Cache-Control: no-cache
Postman-Token: eea13afa-e267-7439-9b04-c57044d057f9

grant_type=password&client_id=test-oauth-client&scope=dss&username=user700&password=12345&resource=test

Приходит ответ с ошибкой — {«error»:»invalid_client»}

Client_ID в DSS прописан правильный:

ClientId : test-oauth-client
ClientName :
Description :
Enabled : True
Flows : {AuthorizationCode}
ClientSecrets : {}
RedirectUris : {urn:ietf:wg:oauth:2.0:oob:auto}
Type : Public
AccessTokenType : Jwt
AuthorizationCodeLifetime : 300
AccessTokenLifetime : 300
IdentityTokenLifetime : 300

В журнале DSS (в STS’e) ошибка — Instance Unique Identifier: 1/STS] Source: ClientValidator Message: Client with id user700 is not registered..

На самом деле Пользователь зарегистрирован в DSS’e.


Вверх


Offline

marrow

 


#8
Оставлено
:

27 сентября 2017 г. 13:53:22(UTC)

marrow

Статус: Активный участник

Группы: Участники

Зарегистрирован: 14.06.2016(UTC)
Сообщений: 56
Мужчина
Российская Федерация

Сказал «Спасибо»: 4 раз
Поблагодарили: 3 раз в 3 постах

AllowedFlow пробовал как и ResourceOwner и ClientCredentials — без успешно.

Возможно ли у вас попросить пример Вашего Get-DSSClient (с dss.cryptopro.ru). И пример запроса обращающий по логину и паролю. Выполнял пример с документации — без успешно.

Так же не очень понятно в Руководство администратора Вы пишите, что параметр ClientCredentials не доступен, а в Руководство разработчика есть описание и примеры запроса и ответа — «Авторизации с использование учётных данных пользователя» Anxious

Отредактировано пользователем 27 сентября 2017 г. 14:23:16(UTC)
 | Причина: Не указана


Вверх

Пользователи, просматривающие эту тему

Guest

Быстрый переход
 

Вы не можете создавать новые темы в этом форуме.

Вы не можете отвечать в этом форуме.

Вы не можете удалять Ваши сообщения в этом форуме.

Вы не можете редактировать Ваши сообщения в этом форуме.

Вы не можете создавать опросы в этом форуме.

Вы не можете голосовать в этом форуме.

Exception handling is an important aspect in any software application development. An exception is an event that occurs during the execution of a program that disrupts the normal flow of instructions. When the exception occurs in a Web Service, it will be propagated to the client as a SOAP fault. This article will help you understand different types of exceptions that could be thrown inside the Web Service and how user defined exceptions can improve error handling in your Web Service.

Different Types of Exceptions

Exceptions could be thrown inside a Web Service for various reasons. The possible types of exceptions that could be thrown are RuntimeException, RemoteException, SOAPFaultException and User Defined Exception.

The Web Service developer might try throwing a RuntimeException such as NullPointerException or ArrayIndexOutOfBoundsException inside the Web Service. But, throwing RuntimeException inside the Web Service is considered to be a bad exercise because RuntimeException will always be converted into RemoteException at the client side. While the client is waiting to catch the RuntimeException after invoking a Web Service, he will get only the RemoteException instead of RuntimeException. Eventually, he cannot perform proper error handling for RuntimeException.

The problem with throwing RemoteException is that the different client side libraries will interpret this exception in different ways. It is not portable.

The appropriate exception that the Web Service application could throw is SOAPFaultException. The SOAPFaultException contains four parts: faultcode, faultstring, actor, and detail. This exception can give you the complete information about the error condition. The faultcode might tell you whether the error has happened because of the Server, Client, or something else. For example, when a client doesn’t provide security information such as username and password in the HTTP/SOAP header but the service mandates them, the pre-processing logic in the service implementation might obviously throw an authentication exception. This kind of error is considered to be a Client error. The faultstring contains the corresponding description of the error condition that has happened. This string message is human readable and the developer can easily debug the problem with the help of it. The detail element contains the actual exception message and its complete stack trace. Actually, the detail element is an instance of the javax.xml.soap.Detail class and can be created by using the javax.xml.soap.SOAPFactory.createDetail() API.

User-Defined Exceptions

Although SOAPFaultException gives necessary information that is needed to debug the problem, the Web Service client might want to do something more with a fault message that he had received. The one thing that he might want to do is to have a configurable and dynamic text description of the error that occurred. The other thing could be to have the internationalization support for the error messages. By providing text description in languages other than English, he could try addressing needs of all set of people. The list may grow more and more.

To achieve the previously stated goals, a user-defined exception with some specific format could be thrown in the service. Based on the exception that the client has received, he can decide what to do with fault message. The user-defined exception thrown inside the Web Service is directly mapped into wsdl:fault element in the Web Services Description Language (WSDL) of the Web Service. You could see the fault element as one of the child elements of operation element of the portType. The other two child elements of operation are input and output. The fault element, an optional field in the operation element, defines the abstract format of the error message that might be thrown by the Web Service. The wsdl:message element pertaining to WSDL:fault can contain only one message part, and the message part could be either a complexType or simple XMLType.

I propose here how a user-defined exception, MyCustomException, could be defined to better handle error messages. The MyCustomException contains an appropriate fault message that is as defined in the WSDL definition. The fault message contains the following three parts:

  • Error Code, containing a five-letter identifier plus a three-digit identifier

    For example, GENEX001 could mean a generic error, whereas AUTEX001 could mean an authentication error.

  • Text describing the fault, including substitution variables (mentioned as {0}, {1}, and so forth)

    For example, the corresponding text description for Error Code GENEX001 will be something like “Number that you have entered is {0}.”

  • A list of values corresponding to the substitution variables defined in the above text.

    For example, for the above case, the variable list will contain only one value (say 1) because the text description above contains only one substitution variable.

    After processing the text using relevant logic, the final text description would be “Number that you have entered is 1.”

With the above approach:

  • Faults can be identified, using the error code, without the need for applications or people to parse or understand the fault text (which may be in a unknown language).
  • Text description can be defined in many languages, and corresponding variables can be placed accordingly in a language-independent manner.
  • Internationalization support can be offered by the Services by providing alternate language forms of fault messages automatically by replacing the text description portion only.

Sample: Service, Exception Class, WSDL, and Client

In this section, you will see a sample for service, exception, WSDL, and client. These samples will use Weblogic implementation.

Service Implementation

This service takes two inputs: int number and String message. If the number is 1, SOAPFaultException will be thrown. If the number is 2, MyCustomException will be thrown; otherwise, the method will return successfully.

package WS.exception;
import javax.xml.soap.SOAPException;
import javax.xml.soap.SOAPFactory;
import javax.xml.soap.Detail;

public class ExceptionService{
   public String echo(int number, String message)
          throws MyCustomException{
      System.out.println("Number: "+number+", Message: " + message);
      switch(number){
         case 2:
            throw new MyCustomException(
            "GENEX001",
            "Number that you have entered is {0}",
            new String[]{String.valueOf(number)}
               );
         case 1:
            Detail detail = null;
            try{
               detail = SOAPFactory.newInstance().createDetail();
               //add error message here
               detail.addTextNode(
                  "Choice 1 means SOAPFaultException");
            }catch(SOAPException ex){
               throw new MyCustomException(
                  "SEREX001",
                  "Error while creating detail element",
                  new String(){});
            }

            throw new javax.xml.rpc.soap.SOAPFaultException(
               new javax.xml.namespace.QName("env.Server"),
               "Number that you have entered is "+number,
               "NO ACTOR",
               detail);
      }

      return "SUCCESS";
   }
}

MyCustomException class

The pseudo implementation for the custom exception is given below:

package WS.exception;
public class MyCustomException extends Exception{
   private String   errorCode;
   private String   errorDescription;
   private String[] variables;

   public MyCustomException(String errorCode,
                            String errorDescription,
                            String[] variables){
      this.errorCode = errorCode;
      this.errorDescription = errorDescription;
      this.variables = variables;
   }
   //all setter and getter methods need to be implemented here
}

WSDL Fault

The description of wsdl:fault is given below:

  <xsd:schema xmlns_xsd="http://www.w3.org/2001/XMLSchema"
    xmlns_stns="java:WS.exception"
    elementFormDefault="qualified"
    attributeFormDefault="qualified"
    targetNamespace="java:WS.exception">
   <xsd:import namespace="java:language_builtins.lang">
   </xsd:import>
   <xsd:element type="stns:MyCustomException"
     name="MyCustomException">
   </xsd:element>
   <xsd:complexType name="MyCustomException">
    <xsd:sequence>
     <xsd:element type="xsd:string"
       name="errorCode"
       minOccurs="1"
       nillable="true"
       maxOccurs="1">
     </xsd:element>
     <xsd:element type="xsd:string"
       name="errorDescription"
       minOccurs="1"
       nillable="true"
       maxOccurs="1">
     </xsd:element>
     <xsd:element xmlns_tp="java:language_builtins.lang"
       type="tp:ArrayOfString"
       name="variables"
       minOccurs="1"
       nillable="true"
       maxOccurs="1">
     </xsd:element>
    </xsd:sequence>
   </xsd:complexType>
</xsd:schema>

<message name="MyCustomException">
  <part  xmlns_partns="java:WS.exception"
    type="partns:MyCustomException"
    name="MyCustomException">
  </part>
 </message>

<portType name="ESPort">
  <operation name="echo">
   <input message="tns:echo">
   </input>
   <output message="tns:echoResponse">
   </output>
   <fault name="MyCustomException"
     message="tns:MyCustomException">
   </fault>
  </operation>
 </portType>

Client Implementation

Web Services can be invoked using two approaches:

  1. Using stubs
  2. Using Dynamic Invocation Interface (DII)

Following is the client implementation using DII:

import java.util.*;
import javax.xml.namespace.QName;
import javax.xml.rpc.*;
import javax.xml.rpc.soap.SOAPFaultException;

public class ExceptionService{
   public static void main(String[] args) throws Exception{
     System.setProperty(
         ServiceFactory.SERVICEFACTORY_PROPERTY,
         "weblogic.webservice.core.rpc.ServiceFactoryImpl");

      ServiceFactory factory = ServiceFactory.newInstance();
      Service service = factory.createService(new QName(""));
      Call call = service.createCall();

      call.addParameter("intVal",
                        new QName("http://www.w3.org/2001/XMLSchema",
                        "int"), ParameterMode.IN);
      call.addParameter("string",
         new QName("http://www.w3.org/2001/XMLSchema", "string"),
         ParameterMode.IN);
      call.setOperationName(new QName("http://tempuri.org", "echo"));
      call.setReturnType(
         new QName("http://www.w3.org/2001/XMLSchema", "string"));
      call.setTargetEndpointAddress("http://localhost/exception/ES");
      Object[] argArray = {new Integer(args[0]), "how are you"};
      Object resultObj = null;
      try{
         resultObj = call.invoke(argArray);
      }catch(SOAPFaultException fault){
         fault.printStackTrace();
         resultObj = "ERROR Caught";

         System.out.println("Fault Detail : "+ fault.getDetail());
         System.out.println("Fault Actor : "+ fault.getFaultActor());
         System.out.println("Fault String: "+ fault.getFaultString());
      }

      System.out.println("Result: "+resultObj);
   }
}

When you generate stubs using the Weblogic clientgen utility, you would be able to catch MyCustomeException itself on the client side. The sample code is given below:

package WS.exception;
import java.text.MessageFormat;
public class Client {
   public static void main(String[] args ) throws Exception{
      System.setProperty(
      "javax.xml.rpc.ServiceFactory",
      "weblogic.webservice.core.rpc.ServiceFactoryImpl");

      ES_Impl ws = new ES_Impl(args[0]);
      ESPort port  = ws.getESPort();

      String returnVal = null;
      try{
         returnVal = port.echo(Integer.parseInt(args[1]),
                               "A for Apple");
   }catch(MyCustomException ex){
      System.out.println("MyCustomException occurred:");
      //ex.printStackTrace();
      String errorCode = ex.getErrorCode();
      String errorDescription = ex.getErrorDescription();
      String[] variables = ex.getVariables();

      String resolvedErrorMsg = MessageFormat.format(
                                errorDescription, variables);
      if(errorCode.startsWith("AUT")){
         //Authentication error: do something
      }else if(errorCode.startsWith("MSG")){
         //SOAP Message error: do something
      }else{
         //General error: do something
      }
   }catch(Exception ex){
      System.out.println("One of the other Exceptions occurred:");
      ex.printStackTrace();
   }
   System.out.println(returnVal);
   }
}

In the program above, after catching MyCustomException, you can get the error code, text, and variables. Based on the error, you can segregate the type of error that had happened. If you want, you can use the text description that comes with the excerption. Otherwise, you can fetch the text description which in other language from a database, or a disk file that is associated with the error code. You can store the error code and description as a name-value pair in a disk file or a database. This will really help you manage internationalization of the error message. Also, MessageFormat class will help you get the dynamic error message.

SOAP Response 1 (when a SOAPFaultException is thrown)

Following is the SOAP response that I got while the service had thrown SOAPFaultException.

<env:Envelope xmlns_env="http://schemas.xmlsoap.org/soap/envelope/"
              xmlns_xsi="http://www.w3.org/2001/XMLSchema-instance"
              xmlns_soapenc="http://schemas.xmlsoap.org/soap/encoding/"
              xmlns_xsd="http://www.w3.org/2001/XMLSchema">
   <env:Body>
      <env:Fault xmlns_fault="">
         <faultcode>fault:env.Server</faultcode>
         <faultstring>Number that you have entered is 1</faultstring>
         <faultactor>NO ACTOR</faultactor>
         <detail>Choice 1 means SOAPFaultException</detail>
      </env:Fault>
   </env:Body></env:Envelope>

SOAP Response 2 (when MyCustomException is thrown)

Following is the SOAP response that I got while the service had thrown MyCustomException.

<env:Envelope xmlns_env="http://schemas.xmlsoap.org/soap/envelope/"
              xmlns_xsi="http://www.w3.org/2001/XMLSchema-instance"
              xmlns_soapenc="http://schemas.xmlsoap.org/soap/encoding/"
              xmlns_xsd="http://www.w3.org/2001/XMLSchema">
   <env:Body>
      <env:Fault>
         <faultcode>env:Server</faultcode>
         <faultstring>Service specific exception:
                      WS.exception.MyCustomException</faultstring>
         <detail>
            <MyCustomException xmlns_n1="java:WS.exception"
                               xsi_type="n1:MyCustomException">
               <errorCode xsi_type="xsd:string">GENEX001</errorCode>
               <errorDescription xsi_type="xsd:string">
                  Number that you have entered is {0}
               </errorDescription>
               <variables soapenc_arrayType="xsd:string[1]">
                  <string xsi_type="xsd:string">2</string>
               </variables>
            </MyCustomException>
         </detail>
      </env:Fault>
   </env:Body></env:Envelope>

Conclusion

This article has discussed various exceptions in Web Service and how a user-defined exception could be used for effective error handling in Web Services.

About the Author

Ayyappan Gandhirajan holds a Bachelor’s degree in Electronics & Communication Engineering from MK University, India and is pursuing a Master’s in Software Systems from BITS, Pilani. He has been working as an Associate System Analyst for Hewlett-Packard, Bangalore. He has more than six years of software experience involving Web services, WS Security, and J2EE technologies. He is currently involved in Web services orchestration and access controllers. He can be reached at [email protected] or [email protected].

Using SOAP Faults and Exceptions in Java JAX-WS Web Services

Pick up a copy of Java SOA Cookbook by Eben Hewitt for more stuff like this.

This article shows you how to avoid this error: javax.xml.ws.soap.SOAPFaultException: java.lang.NoSuchMethodException

This article shows you how to create proper throws clauses in your Java web services, and how to write JUnit 4.4 unit tests to handle the exceptions that you get, and mapping semantics with Java exceptions and SOAP Faults. It also shows you how to use the @WebFault annotation.

If you see a stack trace like this in your Java web service client, the answer is below:

javax.xml.ws.soap.SOAPFaultException: java.lang.NoSuchMethodException: com.example.MyExceptionBean.setMessage(java.lang.String)
        at com.sun.xml.internal.ws.fault.SOAP11Fault.getProtocolException(SOAP11Fault.java:171)
        at com.sun.xml.internal.ws.fault.SOAPFaultBuilder.createException(SOAPFaultBuilder.java:94)
        at com.sun.xml.internal.ws.client.sei.SyncMethodHandler.invoke(SyncMethodHandler.java:240)
        at com.sun.xml.internal.ws.client.sei.SyncMethodHandler.invoke(SyncMethodHandler.java:210)
        at com.sun.xml.internal.ws.client.sei.SEIStub.invoke(SEIStub.java:103)
        at $Proxy33.verify(Unknown Source)

I.
Let’s start with a regular Java class with an operation that throws an exception, like this:

public class CheckVerify {
    public MessageResponseType verify(CheckType check)
        throws MyException { … }
}

Because annotations are so easy in JAX-WS, I would expect that I could turn such a class into a Web Service using annotations, have the deployment tool run wsgen and create the web service artifacts (WSDL and XML Schema) for me, which it would. I would expect that Java would handle the exception for me like it does everything else: it turns the regular method into an ‘operation’ in the WSDL—it should also turn the ‘throws MyException’ into a ‘<soap:fault name=»MyException» use=»literal»/>’ in the WSDL too. It does.

So what’s the problem?

The problem is that while this web service will deploy, this doesn’t actually work for a generated Java client of that web service. You need to know a little more, and make use of an additional annotation and something called a fault bean. This article shows you how.

II.

When implementing a web service using Java and JAX-WS, you might want to code in a natural style that allows you to throw an exception from your service operation, and have the runtime translate that into a SOAP fault that is received on the client.

You can code exceptions in JAX-WS, but the documentation on the web for this is practically non-existent, which is strange because it’s such a common thing for Java programmers to want to do. Sometimes you have no choice but to deal with a checked exception that an underlying library throws (IOException is common). We need to know how to deal with this.

Say we have the following web service—the annotated version of the class we started with above. It’s called CheckVerify and it defines a single operation that makes sure that a check writing customer is not known to the bad check writer database:

@WebService(
    serviceName=»CheckVerifyService»,
    portName=»CheckVerify»,
    targetNamespace=»
http://www.example.com«)
public class CheckVerify {
    @WebMethod(operationName=»verify»)
    public @WebResult(name=»checkVerifyResponse»,
            partName=»checkVerifyResponse»,
            targetNamespace=»
http://www.example.com«)
            MessageResponseType
    verify(
    @WebParam(name=»check»,
        partName=»check»,
        targetNamespace=»
http://www.example.com«)
        CheckType check)
        throws CheckVerifyFault {
    //…
 }
}

This operation throws a CheckVerifyFault. Say that our implementation of the verify method actually calls a second, remote web service that uses HTTPS to validate the check, or goes to a database using JDBC. There might be checked Java exceptions that we want to translate into a SOAP Fault to use to return to the client.

Here’s the portType snippet of the WSDL that results from these annotations:

<portType name=»CheckVerify»>
<operation name=»verify»>
<input message=»tns:verify» />
<output message=»tns:verifyResponse» />
<fault message=»tns:MyException» name=»MyException» />
</operation>
</portType>

While the above code will deploy to a container such as WebLogic, it won’t have the desired result on the client.

First of all, JAX-WS will create an exception class for us, which is nice. But the exception class will be called MyException_Exception on the client side. Doing what we want is a more complicated and obscure part of the JAX-WS model, and using exceptions is not quite as easy as other things in JAX-WS.

If we run wsimport before our automated test, then compile the generated code and run the test, we’ll see what effect this code has on the client view. And we’ll have a good basis for undersanding the client side of this.

First we know that we want to change the name of the generated exception to something more friendly. So let’s use bindings file to customize the generated code. You can read more about this in Java SOA Cookbook, but if you’re using Maven to run the build that executes your wsimport, you can put a file called bindings.xml in the src/jaxws folder. Give that file the following contents:

<?xml version=»1.0″ encoding=»UTF-8″?>
<bindings
    xmlns=»
http://java.sun.com/xml/ns/jaxws«
    xmlns:wsdl=»
http://schemas.xmlsoap.org/wsdl/«>
    <bindings node=»wsdl:definitions/wsdl:portType[@name=’CheckVerify’]/wsdl:operation[@name=’verify’]/wsdl:fault[@name=’MyException’]»>
        <class name=»MyFault»>
            <javadoc>Exception generated during any operation with the service.</javadoc>
        </class>
    </bindings>
</bindings>

This uses XPath to find the node in the generated WSDL that matches the fault with the name of «MyException» and indicates that the generated class should be named MyFault.

JAX-WS will create two classes now: MyFault, which is the JAXB customization re-name of the MyException class, and a class called MyException. That class will be a bean that holds a message.

The generated MyFault class on the client looks like this:

@WebFault(name = «MyException», targetNamespace = «http://www.example.com«)
public class MyFault extends Exception {

    /**
     * Java type that goes as soapenv:Fault detail element.
     */
    private MyException faultInfo;

    public MyFault(String message, MyException faultInfo) {
        super(message);
        this.faultInfo = faultInfo;
    }

    public MyFault(String message, MyException faultInfo, Throwable cause) {
        super(message, cause);
        this.faultInfo = faultInfo;
    }

    public MyException getFaultInfo() {
        return faultInfo;
    }

}

The class is annotated with @WebFault, but indicates in its ‘name’ attribute that it is called MyException, which is the bean class (shown below) that we were renaming in our JAXB XML customization file.

So this is where things start getting weird. Notice that a MyFault constructor takes a MyException type. There is not a no-arg constructor in MyFault. The faultInfo (of type MyException) is expected to contain the SOAP Fault detail information. That is, there is a class (here, MyException, that holds the data element value of the <detail> element child of the <soap:fault> in the underlying SOAP envelope—the exception class is not doing that work for us.

So the first thing to understand is that MyException is not an exception type at all, but a regular bean that acts as a holder for the SOAP Fault information, to ensure it complies with that contract (because a SOAP Fault is not the same as a Java checked exception; checked exceptions don’t exist in many languages). Put another way, even if you coded your exception to include a message String along with a getter and setter for it that could hold this info, JAX-WS doesn’t know about it, so you need to define it explicitly.

So here is that generated ‘exception’ class, which is really not an exception at all, and rather a bean that your MyFault class (which actually IS the client-side exception class) accepts.

@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = «MyException», propOrder = {
    «message»
})
public class MyException {

    protected String message;

    public String getMessage() {
        return message;
    }

    public void setMessage(String value) {
        this.message = value;
    }
} //comments deleted

Because the WSDL is valid and JAX-WS generated these classes for you, you might think that everything would work at this point. But it won’t. Let’s write the naive unit test we expect would work around this code on the client.

public class CheckVerifyServiceTest {

    public static final Logger LOGGER = Logger.getLogger(CheckVerifyServiceTest.class);

    private static final String WSDL_URL_KEY = «checkVerify.wsdl.url»;

    private static final QName QNAME = new QName(
            «
http://www.example.com«, «CheckVerifyService»);

    private static CheckVerify checkVerify;

    private static final String TODAY;
    @BeforeClass
    public static void setup() throws Exception {
        LOGGER.debug(«Attempting to initiate service…»);
        String wsdl = System.getProperty(WSDL_URL_KEY);

                LOGGER.debug(«Using WSDL: » + wsdl);
        final URL wsdlUrl = new URL(wsdl);

        final CheckVerifyService service = new CheckVerifyService(wsdlUrl, QNAME);

                checkVerify = service.getCheckVerify();

                        if (checkVerify != null) {
            LOGGER.debug(«Found service stub.»);
        } else {
            fail();
        }
    }

    @Test
    public void testMe() {
        LOGGER.debug(«Executing…»);

        CheckType check = new CheckType();
        //….

        MessageResponseType response = null;
        try {

            response = checkVerify.verify(check);

            LOGGER.debug(«Completed Exception response.»);

        } catch (MyFault ex) {
            LOGGER.error(«Error class: » + ex.getClass().getName());
            LOGGER.error(«Caught error. Message: » + ex.getMessage());

            assertTrue(true);
        }
    }
}

In our @BeforeClass annotated method we use the generated service stub to get the port type for the service, and use that in our tests.

In the @Test method we invoke the verify method that throws the MyException exception (which we renamed to MyFault using JAXB customizations). So we put a try/catch around it and we should be able to expect that if we do something to make the method throw a fault/exception, that it would be caught here and our assertion would pass and everything would be fine, right? Wrong. The above code doesn’t work.

NOTE: The proper way to positively test that your method throws an exception when it is supposed to in JUnit is with the @Test(expected=MyFault.class) annoation attribute. We want to look at the details here, so this is for illustration.

Here’s what happens when you run the above test is that the test compiles but results in an ERROR (not a regular test failure):

testMe(com.dte.soa.checks.ws.CheckVerifyServiceTest)  Time elapsed: 0.094 sec  <<< ERROR!
javax.xml.ws.soap.SOAPFaultException: java.lang.NoSuchMethodException: com.dte.soa.checks.ws.jaxws.MyExceptionBean.setMessage(java.lang.String)
        at com.sun.xml.internal.ws.fault.SOAP11Fault.getProtocolException(SOAP11Fault.java:171)
        at com.sun.xml.internal.ws.fault.SOAPFaultBuilder.createException(SOAPFaultBuilder.java:94)
        at com.sun.xml.internal.ws.client.sei.SyncMethodHandler.invoke(SyncMethodHandler.java:240)
        at com.sun.xml.internal.ws.client.sei.SyncMethodHandler.invoke(SyncMethodHandler.java:210)
        at com.sun.xml.internal.ws.client.sei.SEIStub.invoke(SEIStub.java:103)
        at $Proxy33.verify(Unknown Source)

The problematic thing here is this line:

javax.xml.ws.soap.SOAPFaultException: java.lang.NoSuchMethodException: com.example.MyExceptionBean.setMessage(java.lang.String)

       The problem appears to be that there is no method called setMessage in the MyExceptionBean class. This seems like a bug in JAX-WS, because we didn’t write any class called MyExceptionBean, and it’s not listed in our classes under the Generated Sources, so how could we possibly fix this?

The answer is to do this on the service side:
1. Write a class that extends Exception.
2. Annotate it with @WebFault and point its faultBean attribute to the name of a Java class that has a no-arg constructor, a message String field, and a getter and setter for it. This will be your carrier for that soap:fault detail element.
3. Redeploy your service and regenerate your client. Now the client view will be exactly how you want it. JAX-WS will take any message you supply to your exception type on the server side and put it in the SOAP Fault detail in the SOAP envelope. It will unpack that string message into the fault bean and make it available as the message within the exception you’re catching.

Below are examples of using the @WebFault annotation to deal with SOAP faults and exceptions on the web service side.

We still write the method on the service exactly as before—there’s no @WebFault annotation on the method—it’s a class-level annotation.

    @WebMethod(operationName=»verify»)
    public @WebResult(name=»checkVerifyResponse»,
            partName=»checkVerifyResponse»,
            targetNamespace=»
http://www.example.com«)
            MessageResponseType
    verify(
    @WebParam(name=»check»,
        partName=»check»,
        targetNamespace=»
http://www.example.com«)
        CheckType check)
        throws CheckVerifyFault {

Now we’ll write that CheckVerifyFault class:

@WebFault(name=»CheckVerifyFault»,
    targetNamespace=»
http://www.example.com«)
public class CheckVerifyFault extends Exception {

    /**
     * Java type that goes as soapenv:Fault detail element.
     */
    private CheckFaultBean faultInfo;

    public CheckVerifyFault(String message, CheckFaultBean faultInfo) {
        super(message);
        this.faultInfo = faultInfo;
    }

    public CheckVerifyFault(String message, CheckFaultBean faultInfo, Throwable cause) {
        super(message, cause);
        this.faultInfo = faultInfo;
    }

    public CheckFaultBean getFaultInfo() {
        return faultInfo;
    }
}

This class extends Exception, and indicates that it takes a CheckFaultBean. So in Java web services we don’t have the luxury of just using any checked exception that we have lying around; we’ll have to annotate it, add the constructors that take our Bean info object, and then create that Bean info class. Here’s what that looks like:

/**
 * The Java type that goes as soapenv:Fault detail element.
 * Used in web services exceptions, fault beans just hold the details
 * of the SOAP fault. This one is used by the
{@link CheckVerifyFault).
 *
 * @author eben hewitt
 */
public class CheckFaultBean {

    private String message;

    public CheckFaultBean() { }

    public String getMessage() {
        return message;
    }

    public void setMessage(String message) {
        this.message = message;
    }
}

Now you’ve got something that matches the SOAP semantics better, and we can recompile and redeploy the web service, then regenerate our client artifacts. Because I’ve renamed the exception class here, I’ll need to update my bindings.xml file too, of course.

We also need to use this bean info in our service method. So instead of just throwing exception, we populate the fault bean with the data for the SOAP Fault Detail, and pass that into our exception; JAX-WS will handle the rest.

Here is our update service operation:

public MessageResponseType verify(CheckType check)
  throws CheckVerifyFault {

        LOGGER.debug(«Executing verify method in Check web service.»);

        if (check == null) {
                final String msg = «The Check cannot be null.»;
                LOGGER.debug(msg);
                CheckFaultBean faultBean = new CheckFaultBean();
                faultBean.setMessage(msg);
                throw new CheckVerifyFault(«This is the Basic Message.», faultBean);
            }
    //do work…
}

Notice that we create a bean instance, put our message for the client in that, then construct the exception and throw it. We can include two messages: the one associated with the exception string, and the more detailed message that is the string value of the FaultInfo object.

Here is the updated test case. It passes a null parameter to the verify method. That’s just the condition the verify method is looking for to throw an exception:

@Test
    public void testException() {
        LOGGER.debug(«Executing…»);

        CheckType check = new CheckType();

        MessageResponseType response = null;
        try {

            response = checkVerify.verify(null);

            LOGGER.debug(«Completed Exception response.»);

        } catch (CheckVerifyFault ex) {
            LOGGER.error(«Error class: » + ex.getClass().getName());
            LOGGER.error(«Caught error. Message: » + ex.getMessage());
            LOGGER.error(«Detailed Message: » + ex.getFaultInfo().getMessage());

                        assertTrue(true);
        }
    }

Running this test gives us just the result that we want:

7/1/09-17:15 ERROR com.example.CheckVerifyServiceTest.testException — Error class: com.discounttire.checkverify.service.CheckVerifyFault
7/1/09-17:15 ERROR com.example.CheckVerifyServiceTest.testException — Caught error. Message: This is the Basic Message.
7/1/09-17:15 ERROR com.example.CheckVerifyServiceTest.testException — Detailed Message: The Check cannot be null.


BUILD SUCCESSFUL
————————————————————————
Total time: 10 seconds
Finished at: Wed Jul 01 17:15:54 MST 2009
Final Memory: 25M/153M

Now you can see that:
1. The test actually allows a totally natural client feel for using Java exceptions and SOAP faults.
2. The string that we populated the exception with on the service-side is readily visible to the client.
3. We get both the regular string message in the exception, and the detail in the fault info bean.

To read more about Java web services and SOAP, pick up a copy of my new  book, Java SOA Cookbook from Amazon.

The comments to this entry are closed.

/* * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. * * Copyright (c) 2003-2018 Oracle and/or its affiliates. All rights reserved. * * The contents of this file are subject to the terms of either the GNU * General Public License Version 2 only («GPL») or the Common Development * and Distribution License(«CDDL») (collectively, the «License»). You * may not use this file except in compliance with the License. You can * obtain a copy of the License at * https://oss.oracle.com/licenses/CDDL+GPL-1.1 * or LICENSE.txt. See the License for the specific * language governing permissions and limitations under the License. * * When distributing the software, include this License Header Notice in each * file and include the License file at LICENSE.txt. * * GPL Classpath Exception: * Oracle designates this particular file as subject to the «Classpath» * exception as provided by Oracle in the GPL Version 2 section of the License * file that accompanied this code. * * Modifications: * If applicable, add the following below the License Header, with the fields * enclosed by brackets [] replaced by your own identifying information: * «Portions Copyright [year] [name of copyright owner]» * * Contributor(s): * If you wish your version of this file to be governed by only the CDDL or * only the GPL Version 2, indicate your decision by adding «[Contributor] * elects to include this software in this distribution under the [CDDL or GPL * Version 2] license.» If you don’t indicate a single choice of license, a * recipient has the option to distribute your version of this file under * either the CDDL, the GPL Version 2 or to extend the choice of license to * its licensees as provided above. However, if you add GPL Version 2 code * and therefore, elected the GPL Version 2 license, then the option applies * only if the new code is made subject to such option by the copyright * holder. */ package javax.xml.rpc.soap; import javax.xml.namespace.QName; import javax.xml.soap.Detail; /** The <code>SOAPFaultException</code> exception represents a * SOAP fault. * * <p>The message part in the SOAP fault maps to the contents of * <code>faultdetail</code> element accessible through the * <code>getDetail</code> method on the <code>SOAPFaultException</code>. * The method <code>createDetail</code> on the * <code>javax.xml.soap.SOAPFactory</code> creates an instance * of the <code>javax.xml.soap.Detail</code>. * * <p>The <code>faultstring</code> provides a human-readable * description of the SOAP fault. The <code>faultcode</code> * element provides an algorithmic mapping of the SOAP fault. * * <p>Refer to SOAP 1.1 and WSDL 1.1 specifications for more * details of the SOAP faults. * * @version 1.0 * @author Rahul Sharma * @see javax.xml.soap.Detail * @see javax.xml.soap.SOAPFactory#createDetail **/ public class SOAPFaultException extends java.lang.RuntimeException { private QName faultcode; private String faultstring; private String faultactor; private Detail detail; /** Constructor for the SOAPFaultException * @param faultcode <code>QName</code> for the SOAP faultcode * @param faultstring <code>faultstring</code> element of SOAP fault * @param faultactor <code>faultactor</code> element of SOAP fault * @param faultdetail <code>faultdetail</code> element of SOAP fault * * @see javax.xml.soap.SOAPFactory#createDetail **/ public SOAPFaultException(QName faultcode, String faultstring, String faultactor, javax.xml.soap.Detail faultdetail) { super(faultstring); this.faultcode = faultcode; this.faultstring = faultstring; this.faultactor = faultactor; this.detail = faultdetail; } /** Gets the <code>faultcode</code> element. The <code>faultcode</code> * element provides an algorithmic mechanism for identifying the * fault. SOAP defines a small set of SOAP fault codes covering * basic SOAP faults. * * @return QName of the faultcode element **/ public QName getFaultCode() { return this.faultcode; } /** Gets the <code>faultstring</code> element. The <code>faultstring</code> * provides a human-readable description of the SOAP fault and * is not intended for algorithmic processing. * * @return faultstring element of the SOAP fault **/ public String getFaultString() { return this.faultstring; } /** Gets the <code>faultactor</code> element. The <code>faultactor</code> * element provides information about which SOAP node on the * SOAP message path caused the fault to happen. It indicates * the source of the fault. * * @return <code>faultactor</code> element of the SOAP fault **/ public String getFaultActor() { return this.faultactor; } /** Gets the detail element. The detail element is intended for * carrying application specific error information related to * the SOAP Body. * * @return <code>detail</code> element of the SOAP fault * @see javax.xml.soap.Detail **/ public Detail getDetail() { return this.detail; } }

Понравилась статья? Поделить с друзьями:
  • Javax servlet error message
  • Javax persistence rollbackexception error while committing the transaction
  • Javax persistence persistenceexception error attempting to apply attributeconverter
  • Javascript обработка ошибок
  • Javascript как изменить цвет текста