I want to create a rest api where i send the json request payload and it should change the json key value based on rule defined using rule mediator
i have already tried the Sample 600 and modified with below code to achieve my requirement.
<rule xmlns:brs="http://wso2.org/carbon/rules">
<source xpath="//val"/>
<target action="replace" resultXpath="//val" xpath="//val"/>
<ruleSet>
<properties/>
<rule resourceType="regular" sourceType="inline"><![CDATA[
rule Invokeval
when
val: String()
eval(val.equals("someval"))
then update(drools.getWorkingMemory().getFactHandle(val),"WORKINGDROOL");
end
]]></rule>
</ruleSet>
<input namespace="http://services.samples" wrapperElementName="jsonObject">
<fact elementName="val" namespace="http://services.samples" type="java.lang.String" xpath="//val"/>
</input>
<output namespace="http://services.samples" wrapperElementName="jsonObject">
<fact elementName="val" namespace="http://services.samples" type="java.lang.String"/>
</output>
</rule>
getting RuleMediator invalde source value Error
Related
I've trying to create a simple data service that inserts an entry in our database with the following definition:
<data name="RESTLoggerDataService" serviceNamespace="" transports="http https">
<config id="default">
<property name="driverClassName">com.microsoft.sqlserver.jdbc.SQLServerDriver</property>
<property name="url">jdbc:sqlserver://SERVER:1433;databaseName=DB</property>
<property name="username">user</property>
<property name="password">pass</property>
</config>
<query id="CreateLog" useConfig="default">
<sql>INSERT INTO Log (Date, Username, ServiceID) VALUES (?,?,?)</sql>
<param name="Date" paramType="SCALAR" sqlType="STRING" type="IN" ordinal="1"/>
<param name="Username" paramType="SCALAR" sqlType="STRING" type="IN" ordinal="2"/>
<param name="ServiceID" paramType="SCALAR" sqlType="STRING" type="IN" ordinal="3"/>
</query>
<resource method="POST" path="Log">
<call-query href="CreateLog">
<with-param name="Date" query-param="Date"/>
<with-param name="Username" query-param="Username"/>
<with-param name="ServiceID" query-param="ServiceID"/>
</call-query>
</resource>
</data>
It seems this is not quite valid as none of the parameters I'm passing in via a CURL call are binding. I've tried:
curl -X POST -H 'Accept: application/xml' -H 'Content-Type: application/xml' --data "#test.xml" http://localhost:90/services/RESTLoggerDataService/Log
with the following XML:
<_postlog>
<Date>2020-09-15 09:06:00.000</Date>
<Username>KIRBJJ</Username>
<ServiceID>WA233</ServiceID>
</_postlog>
but get the following back:
curl: (52) Empty reply from server
curl: (52) Empty reply from server
<axis2ns19:DataServiceFault xmlns:axis2ns19="http://ws.wso2.org/dataservice"><axis2ns19:current_params>{Username=null, Date=null, ServiceID=null}</axis2ns19:current_params><axis2ns19:source_data_service><axis2ns19:data_service_name>RESTLoggerDataService</axis2ns19:data_service_name><axis2ns19:description>Exposing the data service as a REST service.</axis2ns19:description><axis2ns19:location>C:\PROGRA~1\WSO2\ENTERP~1\7154FB~1.0\MICRO-~1\bin\..\tmp\carbonapps\-1234\1600259919991RestLoggerCompositeExporter_1.0.0.car\RESTDataService_1.0.0\RESTDataService-1.0.0.dbs</axis2ns19:location><axis2ns19:default_namespace>http://ws.wso2.org/dataservice</axis2ns19:default_namespace></axis2ns19:source_data_service><axis2ns19:ds_code>DATABASE_ERROR</axis2ns19:ds_code><axis2ns19:nested_exception>com.microsoft.sqlserver.jdbc.SQLServerException: Cannot insert the value NULL into column 'Date', table 'LOGS.dbo.LogEntry'; column does not allow nulls. INSERT fails.</axis2ns19:nested_exception><axis2ns19:current_request_name>_postlog</axis2ns19:current_request_name></axis2ns19:DataServiceFault>
<axis2ns8:DataServiceFault xmlns:axis2ns8="http://ws.wso2.org/dataservice">
<axis2ns8:current_params>{}</axis2ns8:current_params>
<axis2ns8:source_data_service>
<axis2ns8:data_service_name>RESTLoggerDataService</axis2ns8:data_service_name>
<axis2ns8:description>Exposing the data service as a REST service.</axis2ns8:description>
<axis2ns8:location>C:\PROGRA~1\WSO2\ENTERP~1\7154FB~1.0\MICRO-~1\bin\..\tmp\carbonapps\-1234\1600263784524RestLoggerCompositeExporter_1.0.0.car\RESTDataService_1.0.0\RESTDataService-1.0.0.dbs</axis2ns8:location>
<axis2ns8:default_namespace>http://ws.wso2.org/dataservice/LoggingAPI</axis2ns8:default_namespace>
</axis2ns8:source_data_service>
<axis2ns8:ds_code>INCOMPATIBLE_PARAMETERS_ERROR</axis2ns8:ds_code>
<axis2ns8:current_request_name>_postlog</axis2ns8:current_request_name>
</axis2ns8:DataServiceFault>
It appears the input parameters are not binding correctly. Can anybody see what I'm doing wrong?
I have created a similar data service with MySQL and did not face any issues. Could you please try the following and see if it makes any changes. Change the payload by adding namespaces as follows and try the same mediation.
<p:_postlog xmlns:p="http://ws.wso2.org/dataservice">
<xs:Date xmlns:xs="http://ws.wso2.org/dataservice">2020-09-15 09:06:00.000</xs:Date>
<xs:Username xmlns:xs="http://ws.wso2.org/dataservice">KIRBJJ</xs:Username>
<xs:ServiceID xmlns:xs="http://ws.wso2.org/dataservice">WA233</xs:ServiceID>
</p:_postlog>
If this does not work please enable wire logs and confirm that the correct payload is passed to the data service.
Trying to make workable solution for guaranteed delivery In memory.
Create InMemoryStore InMemMessageStore, create and point InsertInvoice
create API so code looking like this :
Sequence:
<?xml version="1.0" encoding="UTF-8"?> <sequence name="InMMSsequence" xmlns="http://ws.apache.org/ns/synapse">
<log level="custom">
<property name="STATE" value="message is sent to InMemMessageStore"/>
</log>
<property name="FORCE_SC_ACCEPTED" scope="axis2" type="STRING" value="True"/>
<axis2ns12:store messageStore="InMemMessageStore" xmlns:axis2ns12="http://ws.apache.org/ns/synapse"/> </sequence>
my API looks like :
<resource methods="POST" uri-template="/sendMessage">
<inSequence>
<sequence key="InMMSsequence"/>
</inSequence>
<outSequence/>
<faultSequence/>
</resource>
Message Processor :
<messageProcessor name="MySMessageProcessor" class="org.apache.synapse.message.processor.impl.forwarder.ScheduledMessageForwardingProcessor" targetEndpoint="InsertInvoice" messageStore="InMemMessageStore" xmlns="http://ws.apache.org/ns/synapse">
<parameter name="interval">1000</parameter>
<parameter name="client.retry.interval">1000</parameter>
<parameter name="max.delivery.attempts">4</parameter>
<parameter name="is.active">true</parameter>
<parameter name="max.delivery.drop">Disabled</parameter>
<parameter name="member.count">1</parameter>
</messageProcessor>
And point :
<endpoint xmlns="http://ws.apache.org/ns/synapse"
name="InsertInvoice">
<http uri-template="http://xxxx.xxx.xxx.xxx/InsertInvoiceVehicleList"
method="post">
<suspendOnFailure>
<progressionFactor>1.0</progressionFactor>
</suspendOnFailure>
<markForSuspension>
<retriesBeforeSuspension>0</retriesBeforeSuspension>
<retryDelay>0</retryDelay>
</markForSuspension> </http> </endpoint>
PROBLEMS:
over PostMan I'm sending the request in JSON format but when I open InMemMessageStore message is in XML ?!? Why?
Endpoint expecting message in JSON format. Probably this is the reason of failure BUT on log I see something like
Failed to send the message through the fault sequence. Sequence name does not Exist.
Is the fault sequence mandatory or it is complaining because I don't have any default error sequence defines at all ?
also
Unable to sendViaPost to url[http://xxx.xxx.xx.xx/InsertInvoiceVehicleList/sendMessage]
Why the 'sendMessage' (This is uritemplate that is defined in API is added on endpoint url ?!?!)
so : Biggest issue here is how to keep message in JSON format and how to keep endpoint url intact ...
I found the problem and I wanted to share it with others ...
1. call end point from API adds postfix on end gives the error
By default, URI template 'sendMessage' will get appended to the target URL when sending messages out. You need to use following property in your sequence to remove URI template from target URL
<property action="remove" name="REST_URL_POSTFIX" scope="axis2"/>.
2. message processor fails to send message to end point
My end point was api .net web service and issue was with HTTP 1.1 chunking,had to disable it since .NET service doesn’t support it.
This setting is in axis2_blocking_client.xml and axis2_client.xml
<parameter name="Transfer-Encoding">chunked</parameter>
3. message processor fails to send message to end point
my seccond End point was servicestack web service and I used end point like
http://xxxx.xxx.xxx.xxx/TMSALSvc/UpdateStatus
but problem was that I needed to specify the reponce format. Once when I put a EndPoint delaration like
http://xxx.xxx.xxx.xx/TMSALSvc/json/reply/UpdateStatus
everything forked
I hope that this can same some times for other facing the same issues
I'm trying to call a web service exposed by third party. After receiving the response I'm wrapping the response to the appropriate class. While marshalling the object of the wrapper class to xml string using "jaxb" I'm getting the error as:
org.apache.camel.NoTypeConversionAvailableException: No type converter
available to convert from type:
com.unifyv4.ws.CreateOrganisationResponse to the required type:
java.io.InputStream with value
com.unifyv4.ws.CreateOrganisationResponse#312ea56e
Detailed Stack Trace:
n | BodyType com.unifyv4.ws.CreateOrganisationResponse
n | Body
com.unifyv4.ws.CreateOrganisationResponse#2c9a5080
n | ]n | n | Stacktracen |
java.io.IOException:
org.apache.camel.NoTypeConversionAvailableException: No type converter
available to convert from type:
com.unifyv4.ws.CreateOrganisationResponse to the required type:
java.io.InputStream with value
com.unifyv4.ws.CreateOrganisationResponse#2c9a5080
at org.apache.camel.converter.jaxb.JaxbDataFormat.marshal(JaxbDataFormat.java:141)[235:org.apache.camel.camel-jaxb:2.15.1.redhat-621084]
at org.apache.camel.processor.MarshalProcessor.process(MarshalProcessor.java:83)[198:org.apache.camel.camel-core:2.15.1.redhat-621084]
at org.apache.camel.management.InstrumentationProcessor.process(InstrumentationProcessor.java:77)[198:org.apache.camel.camel-core:2.15.1.redhat-621084]
at org.apache.camel.processor.RedeliveryErrorHandler.process(RedeliveryErrorHandler.java:448)[198:org.apache.camel.camel-core:2.15.1.redhat-621084]
at org.apache.camel.processor.CamelInternalProcessor.process(CamelInternalProcessor.java:191)[198:org.apache.camel.camel-core:2.15.1.redhat-621084]
at org.apache.camel.processor.Pipeline.process(Pipeline.java:121)[198:org.apache.camel.camel-core:2.15.1.redhat-621084]
at org.apache.camel.processor.Pipeline.access$100(Pipeline.java:44)[198:org.apache.camel.camel-core:2.15.1.redhat-621084]
at org.apache.camel.processor.Pipeline$1.done(Pipeline.java:139)[198:org.apache.camel.camel-core:2.15.1.redhat-621084]
at org.apache.camel.processor.CamelInternalProcessor$InternalCallback.done(CamelInternalProcessor.java:251)[198:org.apache.camel.camel-core:2.15.1.redhat-621084]
at org.apache.camel.processor.RedeliveryErrorHandler$1.done(RedeliveryErrorHandler.java:460)[198:org.apache.camel.camel-core:2.15.1.redhat-621084]
at org.apache.camel.management.InstrumentationProcessor$1.done(InstrumentationProcessor.java:86)[198:org.apache.camel.camel-core:2.15.1.redhat-621084]
at org.apache.camel.processor.SendProcessor$1.done(SendProcessor.java:149)[198:org.apache.camel.camel-core:2.15.1.redhat-621084]
at org.apache.camel.component.cxf.CxfClientCallback.handleResponse(CxfClientCallback.java:61)[207:org.apache.camel.camel-cxf:2.15.1.redhat-621084]
at org.apache.cxf.endpoint.ClientImpl.onMessage(ClientImpl.java:823)[74:org.apache.cxf.cxf-core:3.0.4.redhat-621084]
at org.apache.cxf.transport.http.HTTPConduit$WrappedOutputStream.handleResponseInternal(HTTPConduit.java:1644)[96:org.apache.cxf.cxf-rt-transports-http:3.0.4.redhat-621084]
at org.apache.cxf.transport.http.HTTPConduit$WrappedOutputStream$1.run(HTTPConduit.java:1155)[96:org.apache.cxf.cxf-rt-transports-http:3.0.4.redhat-621084]
at org.apache.cxf.workqueue.AutomaticWorkQueueImpl$3.run(AutomaticWorkQueueImpl.java:428)[74:org.apache.cxf.cxf-core:3.0.4.redhat-621084]
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)[:1.8.0_40]
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)[:1.8.0_40]
at org.apache.cxf.workqueue.AutomaticWorkQueueImpl$AWQThreadFactory$1.run(AutomaticWorkQueueImpl.java:353)[74:org.apache.cxf.cxf-core:3.0.4.redhat-621084]
at java.lang.Thread.run(Thread.java:745)[:1.8.0_40]
Caused by: org.apache.camel.NoTypeConversionAvailableException: No
type converter available to convert from type:
com.unifyv4.ws.CreateOrganisationResponse to the required type:
java.io.InputStream with value
com.unifyv4.ws.CreateOrganisationResponse#2c9a5080
at org.apache.camel.impl.converter.BaseTypeConverterRegistry.mandatoryConvertTo(BaseTypeConverterRegistry.java:177)[198:org.apache.camel.camel-core:2.15.1.redhat-621084]
at org.apache.camel.core.osgi.OsgiTypeConverter.mandatoryConvertTo(OsgiTypeConverter.java:122)[204:org.apache.camel.camel-blueprint:2.15.1.redhat-621084]
at org.apache.camel.converter.jaxb.JaxbDataFormat.marshal(JaxbDataFormat.java:172)[235:org.apache.camel.camel-jaxb:2.15.1.redhat-621084]
at org.apache.camel.converter.jaxb.JaxbDataFormat.marshal(JaxbDataFormat.java:138)[235:org.apache.camel.camel-jaxb:2.15.1.redhat-621084]
... 20 more
Below is the blueprint.xml file and class where I'm trying to marshal the response object.
Blueprint.xml
<cxf:rsServer id="crmRequest" address="http://localhost:9002/rest/" serviceClass="com.spectranet.createEnterpriseCustomer.ReceiveEnterpriseRequest" />
<bean id="crmRequestBean" class="com.spectranet.createEnterpriseCustomer.ReceiveEnterpriseRequest" />
<bean id="myProcessor" class="com.spectranet.createEnterpriseCustomer.MyProcessor" />
<bean id="myProcessor2" class="com.spectranet.createEnterpriseCustomer.MyProcessor2" />
<bean id="dozerConverterLoader" class="org.apache.camel.converter.dozer.DozerTypeConverterLoader">
<argument index="0" ref="myCamel" />
<argument index="1" ref="createOrg" />
</bean>
<bean id="createOrg" class="org.apache.camel.converter.dozer.DozerBeanMapperConfiguration">
<property name="mappingFiles">
<list>
<value>transformation.xml</value>
</list>
</property>
</bean>
<cxf:cxfEndpoint id="unifyCreateOrg" address="http://203.122.58.158:9080/unifyejb/CRMAPI" serviceClass="com.unifyv4.ws.CRMAPI" serviceName="com.unifyv4.ws.CRMAPIService" wsdlURL="wsdl/CRMAPI_WSDL.wsdl" />
<camelContext id="myCamel" xmlns="http://camel.apache.org/schema/blueprint">
<endpoint uri="dozer:createOrg?sourceModel=com.spectranet.createEnterpriseCustomer.CRMCAFRequest&targetModel=com.unifyv4.ws.CreateOrganisation&mappingFile=transformation.xml" id="crmToUnify"/>
<dataFormats>
<jaxb contextPath="generated" id="generated"/>
<jaxb contextPath="com.unifyv4.ws" prettyPrint="true" encoding="UTF-8" partClass="com.unifyv4.ws.CreateOrganisationResponse" id="myPartialJaxb"/>
</dataFormats>
<route>
<from uri="cxfrs:bean:crmRequest" id="crmRequest">
<description/>
</from>
<convertBodyTo type="com.spectranet.createEnterpriseCustomer.CRMCAFRequest"/>
<to pattern="InOut" ref="crmToUnify"/>
<setHeader headerName="Username">
<constant>admin</constant>
</setHeader>
<setHeader headerName="Password">
<constant>admin</constant>
</setHeader>
<setHeader headerName="operationName">
<constant>createOrganisation</constant>
</setHeader>
<setHeader headerName="operationNameSpace">
<constant>http://ws.unifyv4.com/</constant>
</setHeader>
<log message="customer: ${in.body.organisation.customer}"/>
<log message="ipAddress: ${in.body.sessionObject.ipAddress}"/>
<process ref="myProcessor"/>
<to pattern="InOut" uri="cxf:bean:unifyCreateOrg"/>
<marshal ref="myPartialJaxb"/>
<log message="Messsage from soap call is : ${body}"/>
</route>
</camelContext>
Java Code to Marshal the object to xml.
package com.spectranet.createEnterpriseCustomer;
import org.apache.camel.Exchange;
import org.apache.camel.Processor;
import com.unifyv4.ws.CreateOrganisationResponse;
import com.unifyv4.ws.Organisation;
public class MyProcessor2 implements Processor {
public void process(Exchange exchng) throws Exception {
CreateOrganisationResponse orgResponse = new CreateOrganisationResponse();
orgResponse.setReturn(exchng.getIn().getBody(Organisation.class));
System.out.println("Organisation Created : " + orgResponse.getReturn().getOrgNo());
exchng.getIn().setBody(orgResponse);
}
}
Kindly please provide any suggestions if any.
First of all, may I know why you want to marshal ?
Looking at route, I dont think you need to marshal any payload.
Just play around XPATH, XSLT & Camel. Camel becomes more complicated in-fact, if you want to marshal and unmarshal. I am not saying its wrong, I am saying its easier without the hassle of marshal, unmarshal, etc. Because ultimately thats what all frameworks do internally. :)
Eg: https://github.com/gnanagurus/camel-guru-projects/tree/master/camel-cxf-geocoder-example
Cheers
This issue can come when the generated class does not contain XML root element tag. Because of it, framework can not explicitly convert the objects to XML and vice versa.
Hence you are creating the response via processor, please refer your WSDL and create the wrapper response as well.
Thanks
Shiv
I'm implementing a web service using camel cxf to be deployed in Karaf.
I'm using the pax web that comes with karaf. I'm using the cxf codegen plugin in pom to do wsdl to java.
I'm defining the cxf uri and the routes in the RouteBuilder Java DSL. The blueprint.xml only has some beans and ref to the RouteBuilder.
final String cxfUri =
String.format("cxf:%s?serviceClass=%s&wsdlURL=wsdl/Event.wsdl",
"/Event.jws", com.example.EventPortType.class.getCanonicalName());
I have setup ssl with the pax-web(jetty.xml). If i send the WSSE security headers with username and password, it generates a MustUnderstand soap fault.
<wsse:Security xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" S:mustUnderstand="1">
<wsse:UsernameToken xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" wsu:Id="Id-LdZa8aaGdy7mWQWXLp_zpbfg">
<wsse:Username>xxx</wsse:Username>
<wsse:Password Type="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText">xxx</wsse:Password>
</wsse:UsernameToken>
</wsse:Security>
The input request cannot be changed.
I get this exception.
<soap:Fault>
<faultcode>soap:MustUnderstand</faultcode>
<faultstring>MustUnderstand headers: [{http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd}Security] are not understood.</faultstring>
</soap:Fault>
How can i secure the cxf endpoint to authenticate the request?
Thank you.
you need to add a WSS4J interceptors to the exposed CXF service. You can provide your own PasswordCallback for the user validation, but I prefer to leverage the native JAAS. This is a blueprint example requiring the UsernameToken with any Karaf user (this is for exposing a camel-cxf routes, however the same principle applies to the pure CXF implementation). If you prefer Java based Camel route builders, you may add the interceptor beans to the context registry to use them. But - the blueprint (or spring config) allows you to more fine-grained control than simple endpoint parameters.
<?xml version="1.0" encoding="UTF-8"?>
<blueprint
xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:cxf="http://cxf.apache.org/blueprint/core"
xmlns:camelcxf="http://camel.apache.org/schema/blueprint/cxf"
xmlns:cm="http://aries.apache.org/blueprint/xmlns/blueprint-cm/v1.1.0"
xmlns:jaxws="http://cxf.apache.org/blueprint/jaxws"
xsi:schemaLocation="
http://www.osgi.org/xmlns/blueprint/v1.0.0 http://www.osgi.org/xmlns/blueprint/v1.0.0/blueprint.xsd
http://camel.apache.org/schema/cxf http://camel.apache.org/schema/cxf/camel-cxf.xsd http://camel.apache.org/schema/blueprint
http://camel.apache.org/schema/blueprint/camel-blueprint.xsd http://aries.apache.org/blueprint/xmlns/blueprint-cm/v1.1.0
http://svn.apache.org/repos/asf/aries/trunk/blueprint/blueprint-cm/src/main/resources/org/apache/aries/blueprint/compendium/cm/blueprint-cm-1.1.0.xsd
http://cxf.apache.org/blueprint/core http://cxf.apache.org/schemas/blueprint/core.xsd
http://cxf.apache.org/blueprint/jaxws http://cxf.apache.org/schemas/blueprint/jaxws.xsd
http://camel.apache.org/schema/blueprint/cxf http://camel.apache.org/schema/cxf/camel-cxf-2.7.5.xsd">
<bean id="authenticationInterceptor" class="org.apache.cxf.interceptor.security.JAASLoginInterceptor">
<property name="contextName" value="karaf"/>
<property name="roleClassifier" value="RolePrincipal"/>
<property name="roleClassifierType" value="classname"/>
</bean>
<bean id="wsSecInterceptor" class="org.apache.cxf.ws.security.wss4j.WSS4JInInterceptor">
<argument>
<map>
<entry key="action" value="UsernameToken"/>
<entry key="passwordType" value="PasswordText"/>
</map>
</argument>
</bean>
<!-- ================ Apache Camel impl ======================= -->
<camelcxf:cxfEndpoint id="testService2"
address="/api/2.0/external/TestService"
xmlns:apogado="http://test.ws.apogado.com/v1_0/ws"
endpointName="apogado:AddressServicePort"
serviceName="apogado:AddressService"
wsdlURL="classpath:/xsd/ws/TestService.wsdl"
>
<camelcxf:properties>
<entry key="dataFormat" value="PAYLOAD" />
<entry key="ws-security.ut.no-callbacks" value="true"/>
<entry key="ws-security.validate.token" value="false"/>
</camelcxf:properties>
<camelcxf:inInterceptors>
<ref component-id="wsSecInterceptor" />
<ref component-id="authenticationInterceptor"/>
</camelcxf:inInterceptors>
<camelcxf:features>
</camelcxf:features>
</camelcxf:cxfEndpoint>
<camelContext xmlns="http://camel.apache.org/schema/blueprint" id="testWsCtx" trace="true">
<!-- your service implementation -->
<route>
<from uri="testService2" />
<to uri="..." />
<route>
</camelContext>
</blueprint>
I have serached this question on Stackoverflow and found some similar questions but none of them solved my issue. I have compiled all the "proposed" solution but NOTHING works :-(
I have a wsdl and I generated the client code using adb client(Axis 2). The wsdl says that this request will be sent over Https url. I able to successfully create a stub using wsdl to java. However I am not sure how to Basic authentication. The documentation which tells me the details also says that I user name and pwd should be encoded using Base64.
The authentication method used is HTTP Basic . The user name and
password will need to be encoded in a base64 format – UTF8 character
set.
Example: Username:Password = “VXNlcm5hbWU6UGFzc3dvcmQ=”
BTW I have tried this wsdl in SOAP UI and and I am getting correct response but some how my java code won't work
Now Here is the wsdl
<?xml version="1.0" encoding="UTF-8"?>
<definitions targetNamespace="urn:OTSB2B" xmlns="http://schemas.xmlsoap.org/wsdl/" xmlns:apachesoap="http://xml.apache.org/xml-soap" xmlns:impl="urn:OTSB2B" xmlns:intf="urn:OTSB2B" xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" xmlns:wsdlsoap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<wsdl:types>
<schema targetNamespace="urn:OTSB2B" xmlns="http://www.w3.org/2001/XMLSchema" xmlns:urn="urn:OTSB2B">
<simpleType name="tn">
<restriction base="string">
<length value="10"/>
</restriction>
</simpleType>
<simpleType name="prov">
<restriction base="string">
<length value="2"/>
<enumeration value="on"/>
<enumeration value="qc"/>
</restriction>
</simpleType>
<element name="getPresaleByTN">
<complexType>
<sequence>
<element name="tn" type="urn:tn"/>
<element name="prov" type="urn:prov"/>
</sequence>
</complexType>
</element>
<element name="getPresaleByTNReturn" type="xsd:string"/>
<element name="isAlive"/>
<element name="isAliveReturn" type="xsd:boolean"/>
</schema>
</wsdl:types>
<message name="isAliveRequest">
<part element="impl:isAlive" name="isAlive"/>
</message>
<message name="getPresaleByTNRequest">
<part element="impl:getPresaleByTN" name="getPresaleByTN"/>
</message>
<message name="isAliveResponse">
<part element="impl:isAliveReturn" name="isAliveReturn"/>
</message>
<message name="getPresaleByTNResponse">
<part element="impl:getPresaleByTNReturn" name="getPresaleByTNReturn"/>
</message>
<portType name="GetPresaleByTN">
<operation name="getPresaleByTN">
<input message="impl:getPresaleByTNRequest" name="getPresaleByTNRequest"/>
<output message="impl:getPresaleByTNResponse" name="getPresaleByTNResponse"/>
</operation>
<operation name="isAlive">
<input message="impl:isAliveRequest" name="isAliveRequest"/>
<output message="impl:isAliveResponse" name="isAliveResponse"/>
</operation>
</portType>
<binding name="DominoSoapBinding" type="impl:GetPresaleByTN">
<wsdlsoap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http"/>
<operation name="getPresaleByTN">
<wsdlsoap:operation soapAction=""/>
<input name="getPresaleByTNRequest">
<wsdlsoap:body use="literal"/>
</input>
<output name="getPresaleByTNResponse">
<wsdlsoap:body use="literal"/>
</output>
</operation>
<operation name="isAlive">
<wsdlsoap:operation soapAction=""/>
<input name="isAliveRequest">
<wsdlsoap:body use="literal"/>
</input>
<output name="isAliveResponse">
<wsdlsoap:body use="literal"/>
</output>
</operation>
</binding>
<service name="GetPresaleByTNService">
<port binding="impl:DominoSoapBinding" name="Domino">
<wsdlsoap:address location="https://b2b.ivv.bell.ca/ots-qualification-service-tn"/>
</port>
</service>
</definitions>
I have tried this:
GetPresaleByTNServiceStub stub = new GetPresaleByTNServiceStub();
ServiceClient client = stub._getServiceClient();
client.addStringHeader(new QName("userName"), "XXX");
client.addStringHeader(new QName("password"), "YYYYYYYY");
GetPresaleByTNServiceStub.GetPresaleByTN request = new GetPresaleByTN();
Tn tn = new Tn();
tn.setTn("4164390001");
request.setTn(tn);
request.setProv(Prov.on);
GetPresaleByTNReturn response = stub.getPresaleByTN(request);
System.out.println(response.getGetPresaleByTNReturn());
This gives me following error:
org.apache.axis2.AxisFault: Failed to add string header, you have to
have namespaceURI for the QName at
org.apache.axis2.client.ServiceClient.addStringHeader(ServiceClient.java:434)
at com.dinesh.bellAxis.App.main(App.java:30)
Then I tried this
GetPresaleByTNServiceStub stub = new GetPresaleByTNServiceStub();
ServiceClient client = stub._getServiceClient();
HttpTransportProperties.Authenticator basicAuth = new HttpTransportProperties.Authenticator();
basicAuth.setUsername("XXX");
basicAuth.setPassword("CCCCC");
basicAuth.setPreemptiveAuthentication(true);
stub._getServiceClient().getOptions().setProperty(HTTPConstants.AUTHENTICATE, basicAuth);
GetPresaleByTNServiceStub.GetPresaleByTN request = new GetPresaleByTN();
Tn tn = new Tn();
tn.setTn("4164390001");
request.setTn(tn);
request.setProv(Prov.on);
GetPresaleByTNReturn response = stub.getPresaleByTN(request);
System.out.println(response.getGetPresaleByTNReturn());
This gives me the following error:
org.apache.axis2.AxisFault: Transport level information does not match
with SOAP Message namespace URI at
org.apache.axis2.AxisFault.makeFault(AxisFault.java:430) at
org.apache.axis2.transport.TransportUtils.createSOAPMessage(TransportUtils.java:90)
at
org.apache.axis2.description.OutInAxisOperationClient.handleResponse(OutInAxisOperation.java:353)
at
org.apache.axis2.description.OutInAxisOperationClient.send(OutInAxisOperation.java:416)
at
org.apache.axis2.description.OutInAxisOperationClient.executeImpl(OutInAxisOperation.java:228)
at
org.apache.axis2.client.OperationClient.execute(OperationClient.java:163)
at
com.acn.client.GetPresaleByTNServiceStub.getPresaleByTN(GetPresaleByTNServiceStub.java:460)
Next I tried this: which I think is incorrect as it WS Security and not basic auth but what the heck I exhausted all my options
GetPresaleByTNServiceStub stub = new GetPresaleByTNServiceStub();
ServiceClient client = stub._getServiceClient();
OMFactory omFactory = OMAbstractFactory.getOMFactory();
OMElement omSecurityElement = omFactory.createOMElement(new QName( "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd", "Security", "wsse"), null);
OMElement omusertoken = omFactory.createOMElement(new QName("http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd", "UsernameToken", "wsu"), null);
OMElement omuserName = omFactory.createOMElement(new QName("", "Username", "wsse"), null);
omuserName.setText("XXXX");
OMElement omPassword = omFactory.createOMElement(new QName("", "Password", "wsse"), null);
omPassword.addAttribute("Type","http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText",null );
omPassword.setText("YYYYYYY");
omusertoken.addChild(omuserName);
omusertoken.addChild(omPassword);
omSecurityElement.addChild(omusertoken);
stub._getServiceClient().addHeader(omSecurityElement);
GetPresaleByTNServiceStub.GetPresaleByTN request = new GetPresaleByTN();
Tn tn = new Tn();
tn.setTn("4164390001");
request.setTn(tn);
request.setProv(Prov.on);
GetPresaleByTNReturn response = stub.getPresaleByTN(request);
System.out.println(response.getGetPresaleByTNReturn());
This gives the following error:
Exception in thread "main" java.lang.IllegalArgumentException: Cannot
create a prefixed element with an empty namespace name at
org.apache.axiom.om.impl.llom.OMElementImpl.handleNamespace(OMElementImpl.java:186)
at
org.apache.axiom.om.impl.llom.OMElementImpl.(OMElementImpl.java:161)
at
org.apache.axiom.om.impl.llom.factory.OMLinkedListImplFactory.createOMElement(OMLinkedListImplFactory.java:126)
at com.dinesh.bellAxis.App2.main(App2.java:37)
I am not sure what to do next and have checked all the documentation on Apache Axis2 and googled all over the place but could get the code to work.
Any suggestions
Code fragments 1 and 3 don't work because they attempt to create a message that is invalid with respect to SOAP (fragment 1) or XML (fragment 3). Anyway, they attempt to add SOAP headers to the message, which is not what basic auth is about.
Code fragment 2 looks correct. From the stack trace of the exception (more precisely the presence of the handleResponse method) you can see that there is an issue with the response. The error message likely indicates that the content type of the response doesn't match the SOAP version actually used in the response. This means that there is a problem with the service, not with the client.
I found the answer after a lot of trial and error and going over SAAj tutorial on Oracle website.
I able to do Basic authentication using this
String authorization = new sun.misc.BASE64Encoder().encode((“myUserName”+”:”+”myPassword”).getBytes());
headers.addHeader(“Authorization”, “Basic ” + authorization);
Here's the complete tutorial - http://www.javahabit.com/2014/10/17/quick-tutorial-saaj-api/