I have build a client, that should fetch data from a remote, wsdl-based webservice (using SOAP).
But everytime I try to connect (with a call of a function) with the service I get the following exception:
org.springframework.ws.soap.client.SoapFaultClientException: Username and/or Password cannot be null
at org.springframework.ws.soap.client.core.SoapFaultMessageResolver.resolveFault(SoapFaultMessageResolver.java:38) ~[spring-ws-core-2.2.0.RELEASE.jar:2.2.0.RELEASE]
at org.springframework.ws.client.core.WebServiceTemplate.handleFault(WebServiceTemplate.java:826) ~[spring-ws-core-2.2.0.RELEASE.jar:2.2.0.RELEASE]
at org.springframework.ws.client.core.WebServiceTemplate.doSendAndReceive(WebServiceTemplate.java:621) ~[spring-ws-core-2.2.0.RELEASE.jar:2.2.0.RELEASE]
at org.springframework.ws.client.core.WebServiceTemplate.sendAndReceive(WebServiceTemplate.java:555) ~[spring-ws-core-2.2.0.RELEASE.jar:2.2.0.RELEASE]
at org.springframework.ws.client.core.WebServiceTemplate.marshalSendAndReceive(WebServiceTemplate.java:390) ~[spring-ws-core-2.2.0.RELEASE.jar:2.2.0.RELEASE]
at com.test.adminUI.myPartners.client.MyPartnersServiceClient.sendSoapRequest(MyPartnersServiceClient.java:113) [bin/:na]
at com.test.adminUI.myPartners.client.MyPartnersServiceClient.findUser(PartnersServiceClient.java:70) [bin/:na]...
If I put a wrong password for example, the service registered it, an throws a Unauthorized 401 ERROR
So that mean, it actually validates my useraccount details.
my client:
public class MyServiceClient extends WebServiceGatewaySupport {
#Autowired
private ObjectFactory factory;
#Autowired
private SoapProperties adProperties;
private static final String WS_ADDRESSING_URI = "http://www.w3.org/2005/08/addressing";
private static final String TO_TAG = "To";
private static final String ACTION_TAG = "Action";
private static final String WSA_PREFIX = "wsa";
private static final String SOAP_ACTION_FIND_IFXPERSON = adProperties.getsoapURL();
public List<Person> findUser(String email, String globalID) {
List<Person> list = null;
FindPerson findperson = new FindPerson();
try {
findperson.setGlobalID(factory.createGlobalID(globalID));
findperson.setServiceUsername(factory.createServiceUsername(adProperties.getServiceUser()));
findperson.setServicePassword(factory.createServicePassword(adProperties.getServicePassword()));
FindPersonResponse response = (FindPersonResponse) sendSoapRequest(
SOAP_ACTION_FIND_PERSON, findperson);
list = response.getFindPersonResult().getValue();
} catch (Exception ex) {
log.error("could not find Person: ", ex);
}
return null;
}
private Object sendSoapRequest(final String soapAction, Object payLoad) {
Object response = null;
try {
Credentials auth = new NTCredentials(adProperties.getAuthUser(),
adProperties.getAuthPassword(), null, adProperties.getAuthDomain());
HttpClientBuilder clientBuilder = HttpClientBuilder.create();
CredentialsProvider credsProvider = new BasicCredentialsProvider();
credsProvider.setCredentials(AuthScope.ANY, auth);
clientBuilder.setDefaultCredentialsProvider(credsProvider);
RemoveSoapHeadersInterceptor interceptor = new RemoveSoapHeadersInterceptor();
clientBuilder.addInterceptorFirst(interceptor);
HttpClient httpClient = clientBuilder.build();
HttpComponentsMessageSender messageSender = new HttpComponentsMessageSender();
messageSender.setHttpClient(httpClient);
messageSender.setCredentials(auth);
messageSender.afterPropertiesSet();
getWebServiceTemplate().setMessageSender(messageSender);
SaajSoapMessageFactory messageFactory = new SaajSoapMessageFactory(
MessageFactory.newInstance(SOAPConstants.SOAP_1_2_PROTOCOL));
getWebServiceTemplate().setMessageFactory(messageFactory);
response = getWebServiceTemplate().marshalSendAndReceive(
adProperties.getServiceEndpoint(), payLoad, new SoapActionCallback(soapAction) {
public void doWithMessage(WebServiceMessage message) {
try {
SaajSoapMessage soapMessage = (SaajSoapMessage) message;
SOAPMessage saajMessage = soapMessage.getSaajMessage();
SOAPEnvelope envelope = saajMessage.getSOAPPart().getEnvelope();
SOAPHeader header = envelope.getHeader();
QName wsaToQName = new QName(WS_ADDRESSING_URI, TO_TAG, WSA_PREFIX);
SOAPHeaderElement wsaTo = header.addHeaderElement(wsaToQName);
wsaTo.setTextContent(adProperties.getServiceEndpoint());
QName wsaActionQName = new QName(WS_ADDRESSING_URI, ACTION_TAG,
WSA_PREFIX);
SOAPHeaderElement wsaAction = header
.addHeaderElement(wsaActionQName);
wsaAction.setTextContent(soapAction);
} catch (Exception e) {
log.error("", e);
}
}
});
} catch (Exception ex) {
log.error(ex);
}
return response;
}
}
Configuration:
#Configuration
public class MyPartnersServiceConfiguration {
#Bean
public Jaxb2Marshaller marshaller() {
Jaxb2Marshaller marshaller = new Jaxb2Marshaller();
marshaller.setPackagesToScan("com.test.adminUI.myPartners.wsdl");
return marshaller;
}
#Bean
public IFXPartnersServiceClient iFXPartnersServiceClient(Jaxb2Marshaller marshaller) {
IFXPartnersServiceClient client = new IFXPartnersServiceClient();
client.setDefaultUri("http://test.idms.partnersservice");
client.setMarshaller(marshaller);
client.setUnmarshaller(marshaller);
return client;
}
}
Does anybody know what i have to do?
Thanks in advance!
UPDATE
I forgot to mention, that I also get a warning in my console:
o.a.http.impl.auth.HttpAuthenticator: NEGOTIATE authentication error: No valid credentials provided (Mechanism level: No valid credentials provided (Mechanism level: Failed to find any Kerberos tgt))
Is this the problem? What do I have to do in this case?
#Bean
public IFXPartnersServiceClient iFXPartnersServiceClient(Jaxb2Marshaller marshaller) {
IFXPartnersServiceClient client = new IFXPartnersServiceClient();
client.setDefaultUri("http://test.idms.partnersservice");
client.setMarshaller(marshaller);
client.setUnmarshaller(marshaller);
//Set messageSender to client
client.setMessageSender(httpComponentsMessageSender());
return client;
}
Related
I am having trouble fetching result from my amazon elastic search cluster using the amazon java SDK and an IAm user credential. Now the issue is that when the PATH string is equal to "/" then I am able to fetch the result correctly but when I try with a different path for e.g "/private-search" then I get a 403 forbidden error. Even when for the path that has public access I am getting a 403 forbidden error for this IAm user but it works if I remove "signer.sign(requestToSign, credentials);" line in performSigningSteps method(for public resource only).
My policy in AWS gives this IAM user access to everything in my elastic search service. And also what can I do to avoid hard-coding the access key and secret key in source code?
private static final String SERVICE_NAME = "es";
private static final String REGION = "region-name";
private static final String HOST = "host-name";
private static final String ENDPOINT_ROOT = "http://" + HOST;
private static final String PATH = "/private-search";
private static final String ENDPOINT = ENDPOINT_ROOT + PATH;
private static String accessKey = "IAmUserAccesskey"
private static String secretKey = "IAmUserSecretkey"
public static void main(String[] args) {
// Generate the request
Request<?> request = generateRequest();
// Perform Signature Version 4 signing
performSigningSteps(request);
// Send the request to the server
sendRequest(request);
}
private static Request<?> generateRequest() {
Request<?> request = new DefaultRequest<Void>(SERVICE_NAME);
request.setContent(new ByteArrayInputStream("".getBytes()));
request.setEndpoint(URI.create(ENDPOINT));
request.setHttpMethod(HttpMethodName.GET);
return request;
}
private static void performSigningSteps(Request<?> requestToSign) {
AWS4Signer signer = new AWS4Signer();
signer.setServiceName(requestToSign.getServiceName());
signer.setRegionName(REGION);
AWSCredentials credentials = new BasicAWSCredentials(accessKey, secretKey);
signer.sign(requestToSign, credentials);
}
private static void sendRequest(Request<?> request) {
ExecutionContext context = new ExecutionContext();
ClientConfiguration clientConfiguration = new ClientConfiguration();
AmazonHttpClient client = new AmazonHttpClient(clientConfiguration);
MyHttpResponseHandler<Void> responseHandler = new MyHttpResponseHandler<Void>();
MyErrorHandler errorHandler = new MyErrorHandler();
Void response = client.execute(request, responseHandler, errorHandler, context);
}
public static class MyHttpResponseHandler<T> implements HttpResponseHandler<AmazonWebServiceResponse<T>> {
#Override
public AmazonWebServiceResponse<T> handle(com.amazonaws.http.HttpResponse response) throws Exception {
InputStream responseStream = response.getContent();
String responseString = convertStreamToString(responseStream);
System.out.println(responseString);
AmazonWebServiceResponse<T> awsResponse = new AmazonWebServiceResponse<T>();
return awsResponse;
}
#Override
public boolean needsConnectionLeftOpen() {
return false;
}
}
public static class MyErrorHandler implements HttpResponseHandler<AmazonServiceException> {
#Override
public AmazonServiceException handle(com.amazonaws.http.HttpResponse response) throws Exception {
System.out.println("In exception handler!");
AmazonServiceException ase = new AmazonServiceException("exception.");
ase.setStatusCode(response.getStatusCode());
ase.setErrorCode(response.getStatusText());
return ase;
}
#Override
public boolean needsConnectionLeftOpen() {
return false;
}
}
public static String convertStreamToString(InputStream is) throws IOException {
// To convert the InputStream to String we use the
// Reader.read(char[] buffer) method. We iterate until the
// Reader return -1 which means there's no more data to
// read. We use the StringWriter class to produce the string.
if (is != null) {
Writer writer = new StringWriter();
char[] buffer = new char[1024];
try {
Reader reader = new BufferedReader(new InputStreamReader(is, "UTF-8"));
int n;
while ((n = reader.read(buffer)) != -1) {
writer.write(buffer, 0, n);
}
}
finally {
is.close();
}
return writer.toString();
}
return "";
}
The code I'm testing works correctly, logs are right.
Tests in error:
ConnectorTest: Unable to initialize #Spy annotated field 'entity'.
Why can't I use verify on the http entity?
Is there a better way to test it? Should I spy on the logs otherwise?
CLASS TO BE TESTED:
public class Connector {
private static final String hostname = "localhost";
private int varnishPort = 8000;
private int connectionTimeout = 5000; //millis
private int requestTimeout = 5000;
private int socketTimeout = 5000;
private final HttpHost host;
private HttpClient httpClient;
private HttpEntity entity;
private HttpResponse response;
public Connector(){
host = new HttpHost(this.hostname, this.varnishPort);
RequestConfig.Builder requestBuilder = RequestConfig.custom();
requestBuilder = requestBuilder.setConnectTimeout(connectionTimeout);
requestBuilder = requestBuilder.setConnectionRequestTimeout(requestTimeout);
requestBuilder = requestBuilder.setSocketTimeout(socketTimeout);
HttpClientBuilder builder = HttpClientBuilder.create();
builder.setDefaultRequestConfig(requestBuilder.build());
httpClient = builder.build();
}
public void invalidateVarnishCache( String level, String idDb ) {
try{
String xPurgeRegex = level+"/"+idDb+"$";
Header header = new BasicHeader( "X-Purge-Regex", xPurgeRegex );
BasicHttpRequest purgeRequest = new BasicHttpRequest("PURGE", "/" );
purgeRequest.setHeader(header);
response = httpClient.execute(host, purgeRequest);
entity = response.getEntity();
int statusCode = response.getStatusLine().getStatusCode();
if( statusCode >= 300 ){
int respLength = entity.getContent().available();
byte[] errorResp = new byte[ respLength ];
entity.getContent().read(errorResp, 0, respLength);
// log error
}else{
// log success
}
EntityUtils.consume(entity);
}catch(Exception e){
// log exception
}
}
}
MY TEST:
#RunWith(MockitoJUnitRunner.class)
public class ConnectorTest {
#Mock
private HttpClient httpClient;
// #Spy
// private HttpEntity entity;
#InjectMocks
private Connector varnishPurger = new Connector();
#Test
public void purgeFail() throws Exception{
HttpResponse response500 = new BasicHttpResponse( new ProtocolVersion( "HTTP/1.1", 0, 0), 500, "NO!_TEST" );
HttpEntity entity500 = new StringEntity("BAD entity. [test]");
response500.setEntity(entity500);
doReturn( response500 )
.when( httpClient ).execute( isA(HttpHost.class), isA(BasicHttpRequest.class) );
varnishPurger.invalidateVarnishCache("level_test_500", "id_test_500");
// verify( entity, times( 1 ) ).getContent().available(); // HOW DO I MAKE THIS WORK?
}
...
}
HttpEntity is an interface, it cannot be spied, only mocked. So just change the annotation with #Mock, or another option is to declare an initialised instance :
#Spy HttpEntity entity = new BasicHttpEntity();
Anyway the exception message is rather clear on why this happens :
org.mockito.exceptions.base.MockitoException: Unable to initialize #Spy annotated field 'entity'.
Type 'HttpEntity' is an interface and it cannot be spied on.
at org.mockito.internal.runners.JUnit45AndHigherRunnerImpl$1.withBefores(JUnit45AndHigherRunnerImpl.java:27)
at org.junit.runners.BlockJUnit4ClassRunner.methodBlock(BlockJUnit4ClassRunner.java:276)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
at org.mockito.internal.runners.JUnit45AndHigherRunnerImpl.run(JUnit45AndHigherRunnerImpl.java:37)
at org.mockito.runners.MockitoJUnitRunner.run(MockitoJUnitRunner.java:62)
at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:69)
at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:234)
at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:74)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:497)
at com.intellij.rt.execution.application.AppMain.main(AppMain.java:144)
Caused by: org.mockito.exceptions.base.MockitoException: Type 'HttpEntity' is an interface and it cannot be spied on.
... 21 more
This behaviour is aligned with Mockito.spy(Object), this method cannot be invoked if there's no instance.
However the recent Mockito.spy(Class) does not complain about that. This may be a functionality that wasn't ported to the annotation subsystem.
Nonetheless it is semantically wrong to spy on an interface as it doesn't have behaviour.
I solved in this way:
class MockHttpEntity implements HttpEntity{
String msg = "Test_";
InputStream inps;
int count = 0;
public MockHttpEntity(String msg){
this.msg += msg;
inps = IOUtils.toInputStream(this.msg);
}
#Override
public InputStream getContent(){
System.out.println("\n"+(++count)+") Mocked getContent() called.\n");
return inps;
}
public int times(){
return count;
}
#Override public void consumeContent(){ }
#Override public Header getContentEncoding(){ return null; }
#Override public long getContentLength(){ return 0; }
#Override public Header getContentType(){ return null;}
#Override public boolean isChunked(){ return false; }
#Override public boolean isRepeatable(){ return false; }
#Override public boolean isStreaming(){ return false; }
#Override public void writeTo(OutputStream outstream){ }
}
#RunWith(MockitoJUnitRunner.class)
public class ConnectorTest {
#Mock
private HttpClient httpClient;
#InjectMocks
private Connector varnishPurger = new Connector();
#Test
public void purgeFailureResponse() throws Exception{
MockHttpEntity mockedHttpEntity = new MockHttpEntity("bad entity");
HttpResponse response500 = new BasicHttpResponse( new ProtocolVersion( "HTTP/1.1", 0, 0), 500, "NO!_TEST" );
response500.setEntity( mockedHttpEntity );
doReturn( response500 )
.when( httpClient ).execute( isA(HttpHost.class), isA(BasicHttpRequest.class) );
varnishPurger.invalidateVarnishCache("level_test_no", "id_test_no");
Assert.assertTrue( mockedHttpEntity.times() == 2 );
}
...
}
I want to use cookies in Robospice, I have spice service:
public class JsonSpiceService extends SpringAndroidSpiceService {
public RestTemplate createRestTemplate() {
RestTemplate restTemplate = new RestTemplate();
MappingJacksonHttpMessageConverter jsonConverter = new MappingJacksonHttpMessageConverter();
FormHttpMessageConverter formHttpMessageConverter = new FormHttpMessageConverter();
StringHttpMessageConverter stringHttpMessageConverter = new StringHttpMessageConverter();
final List<HttpMessageConverter<?>> listHttpMessageConverters = restTemplate.getMessageConverters();
HttpComponentsClientHttpRequestFactory httpRequestFactory = new HttpComponentsClientHttpRequestFactory();
restTemplate.setRequestFactory( httpRequestFactory );
listHttpMessageConverters.add(jsonConverter);
listHttpMessageConverters.add(formHttpMessageConverter);
listHttpMessageConverters.add(stringHttpMessageConverter);
restTemplate.setMessageConverters(listHttpMessageConverters);
return restTemplate;
}
public CacheManager createCacheManager(Application application) throws CacheCreationException {
CacheManager cacheManager = new CacheManager();
List< Class< ? >> classCollection = new ArrayList< Class< ? >>();
classCollection.add(User.class);
JacksonObjectPersisterFactory jacksonObjectPersisterFactory = new JacksonObjectPersisterFactory(application);
cacheManager.addPersister(jacksonObjectPersisterFactory);
return cacheManager;
}
}
and my Request class:
public class Request extends SpringAndroidSpiceRequest<HttpModel> {
private Context context;
private HttpMethod httpMethod;
private MultiValueMap<String, String> body;
private String link;
private String what;
private Object object;
public Request(Context context, HttpMethod httpMethod, MultiValueMap<String, String> body, String link, String what, Object object) {
super(HttpModel.class);
this.context = context;
this.httpMethod = httpMethod;
this.body = body;
this.link = link;
this.what = what;
this.object = object;
}
#Override
public HttpModel loadDataFromNetwork() throws Exception {
HttpModel httpModel;
HttpHeaders headers = new HttpHeaders();
HttpEntity<?> requestEntity;
if (!what.equals(LOGIN)) {
headers.setContentType(MediaType.APPLICATION_JSON);
} else {
headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
}
requestEntity = new HttpEntity<Object>(body, headers);
ResponseEntity<HttpModel> responseEntity = getRestTemplate().exchange(link, httpMethod, requestEntity, HttpModel.class);
httpModel = responseEntity.getBody();
return httpModel;
}
}
How can i get cookie from response?I try add CookieManager to my Request class, but dont'work:
final CookieManager cookieManager = new CookieManager();
cookieManager.setCookiePolicy(CookiePolicy.ACCEPT_ALL);
CookieHandler.setDefault(cookieManager);
In postman Cookie look like this:
enter link description here
CookieManager is used only for managing cookies in your application's WebViews.
You can use responseEntity.getHeaders().get(COOKIE). You can also try SET_COOKIE or SET_COOKIE2 keys instead of COOKIE, depending on your server's response.
I have created web service using Spring-WS. When I send a request to the web service, this is the response I get in soap-ui:
enter code here
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/">
<SOAP-ENV:Header/>
<SOAP-ENV:Body>
<ns2:SendResponse xmlns:ns2="http://mycompany.com/schema/">
<ns2:SendResult>
<ns2:Token>A00179-02</ns2:Token>
</ns2:SendResult>
</ns2:SendResponse>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
Is there any way to get rid of the "ns2" namespace prefix from the response? I tried a couple of options:
1) Manually updated package-info.java to set the prefix to "":
#XmlSchema(namespace = "http://mycompany.com/schema/",
xmlns = {
#XmlNs(namespaceURI = "http://mycompany.com/schema/", prefix = "")
},
elementFormDefault = javax.xml.bind.annotation.XmlNsForm.QUALIFIED)
package com.example.foo.jaxb;
2) Set the prefix to "" in the QName object in the endpoint class:
return new JAXBElement<SendAndCommitResponse>(new QName("http://mycompany.com/schema/",
"SendResponse",""), SendResponse.class, response);
Both didn't work. How to get rid off the "ns2" namespace prefix?
I eventually found a solution for this.
My problem was caused by JDK 6 not shipping a full version of rt.jar (http://www.oracle.com/technetwork/java/javase/compatibility-137541.html).
I added the following to my maven config
<dependency>
<groupId>com.sun.xml.bind</groupId>
<artifactId>jaxb-impl</artifactId>
<version>2.2.6</version>
</dependency>
And then added
#XmlSchema(namespace = "http://mycompany.com/schema/",
elementFormDefault = javax.xml.bind.annotation.XmlNsForm.UNQUALIFIED).
In the package-info.java (like suggested by #acdcjunior above)
I tried a few of the approaches discussed here, but nothing worked...
Below Class from the link - https://zhuanlan.zhihu.com/p/35298171 fixed my issue
Added the below interceptor to remove the namespaces -
public class PayloadPrefixInterceptor extends TransformerHelper implements EndpointInterceptor {
public static final String NAMESPACE = ObjectFactory.class.getPackage().getAnnotation(XmlSchema.class).namespace();
public static final String XMLNS = "xmlns:";
#Override
public boolean handleRequest(MessageContext messageContext, Object endpoint) throws Exception {
return true;
}
#Override
public boolean handleResponse(MessageContext messageContext, Object endpoint) throws Exception {
WebServiceMessage response = messageContext.getResponse();
Source payloadSource = response.getPayloadSource();
DOMResult result = new DOMResult();
transform(payloadSource, result);
removePrefix(result.getNode());
transform(new DOMSource(result.getNode()), response.getPayloadResult());
return true;
}
private void removePrefix(Node node) {
if (node == null) {
return;
}
if (node.getNodeType() == Node.ELEMENT_NODE) {
removeNamespaceDeclaration(node);
}
if (node.getPrefix() != null) {
node.setPrefix(null);
}
NodeList childNodes = node.getChildNodes();
if (childNodes != null) {
IntStream.of(0, childNodes.getLength()).forEach(index -> removePrefix(childNodes.item(index)));
}
Node nextSibling = node.getNextSibling();
if (nextSibling != null) {
removePrefix(nextSibling);
}
}
private void removeNamespaceDeclaration(Node node) {
NamedNodeMap attributes = node.getAttributes();
IntStream.range(0, attributes.getLength()).forEach(index -> {
Node attribute = attributes.item(index);
if (StringUtils.startsWith(attribute.getNodeName(), XMLNS) &&
StringUtils.equals(attribute.getNodeValue(), NAMESPACE)) {
attributes.removeNamedItemNS(attribute.getNamespaceURI(), attribute.getLocalName());
}
});
}
#Override
public boolean handleFault(MessageContext messageContext, Object endpoint) throws Exception {
return true;
}
#Override
public void afterCompletion(MessageContext messageContext, Object endpoint, Exception ex) throws Exception {
}
}
Registered the interceptor using below -
#EnableWs
#Configuration
public class Config extends WsConfigurerAdapter {
#Override
public void addInterceptors(List<EndpointInterceptor> interceptors) {
interceptors.add(new PayloadPrefixInterceptor());
super.addInterceptors(interceptors);
}
}
it was hard
first: create a class that intercepts soap request and responses:
package examples.webservices.handler;
import java.lang.reflect.Method;
import java.util.Collections;
import java.util.Set;
import javax.xml.namespace.QName;
import javax.xml.soap.SOAPElement;
import javax.xml.soap.SOAPMessage;
import javax.xml.ws.handler.MessageContext;
import javax.xml.ws.handler.soap.SOAPHandler;
import javax.xml.ws.handler.soap.SOAPMessageContext;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
public class CorrigirConteudoRequisicaoSOAP implements SOAPHandler<SOAPMessageContext> {
public Set<QName> getHeaders() {
return Collections.emptySet();
}
public boolean handleMessage(SOAPMessageContext messageContext) {
this.corrigirConteudoRequisicaoSOAP(messageContext);
return true;
}
private void corrigirConteudoRequisicaoSOAP(SOAPMessageContext messageContext){
SOAPMessage msg = messageContext.getMessage();
try {
NodeList childNodes = msg.getSOAPBody().getChildNodes();
for(int k = 0; k < childNodes.getLength(); k++){
Node item = childNodes.item(k);
String localName = item.getLocalName();
{
item.setPrefix("");
Method m = SOAPElement.class.getDeclaredMethod("setElementQName", QName.class);
//I was forced to use reflection because the method setElementQname is not //visible, neither the class that implements it
m.invoke(item, new QName("", item.getLocalName()));
msg.saveChanges();
}
}
} catch (Exception e) {
try {
msg.writeTo(System.out);
} catch (Exception e1) {
e1.printStackTrace();
}
System.out.println();
}
}
public boolean handleFault(SOAPMessageContext messageContext) {
return true;
}
public void close(MessageContext messageContext) {
}
public static void main(String[] args)throws Exception {
}
}
second: associate the service to soap handle
public class PortalFornecedor {
public Usuario getUsuario(){
XIF367Afae09A3344Fbf2E1De819D6EcbaService classeComNomeFeio = new XIF367Afae09A3344Fbf2E1De819D6EcbaService();
Usuario service = classeComNomeFeio.getHTTPPort();
BindingProvider bp = (BindingProvider)service;
Map<String, Object> requestContext = bp.getRequestContext();
requestContext.put(BindingProvider.USERNAME_PROPERTY, "user");
requestContext.put(BindingProvider.PASSWORD_PROPERTY, "pass");
this.handle(service);
return service;
}
public Object getDashboard(){
return "";
}
// here we associate the service to soap handle
private BindingProvider handle(Usuario service) {
BindingProvider bp = (BindingProvider)service;
#SuppressWarnings("rawtypes")
List<Handler> chain = new ArrayList<Handler>();
chain.add(new CorrigirConteudoRequisicaoSOAP());
bp.getBinding().setHandlerChain(chain);
return bp;
}
public static void main(String[] args) {
PortalFornecedor pf = new PortalFornecedor();
Usuario usuario = pf.getUsuario();
LoginExecutarIN in = new LoginExecutarIN();
generated.Usuario user = new generated.Usuario();
user.setLogin("onias");
user.setSenha("12345");
user.setCodigoUsuario(0);
in.setParametroEntrada(user);
try {
LoginExecutarOUT out = usuario.loginExecutar(in);
// SOAPMessageContext.getMessage();
System.out.println(out.getRegistroSelecionado().getNome());
} catch (Exception e) {
e.printStackTrace();
}
}
}
Here is the simple and easiest solution for that problem. Create Package-Info.Java file in your model package and add the below script to that.
#javax.xml.bind.annotation.XmlSchema(namespace = "http://mycompany.com/schema", elementFormDefault = javax.xml.bind.annotation.XmlNsForm.QUALIFIED, xmlns = { #javax.xml.bind.annotation.XmlNs(namespaceURI = "http://mycompany.com/schema", prefix = "") })
package my.com.scicom.stars.model;
And add elementFormDefault as "qualified" in your xsd or wsdl file.
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns="http://mycompany.com/schema"
targetNamespace="http://mycompany.com/schema"
elementFormDefault="qualified">
I am developing a small blackberry project.
Here are the step that it is supposed to be:
User clicks Speak! button. The application record speech voice. [No Problem]
When user finishes speaking, click Stop! button. Once the stop button is clicked, the speech voice will be saved on BB as an AMR file. Then, the file will be sent to web service via ksoap2. Web service will return response as a string of file name. The problem is web service return nothing and there is an error occur: JVM error 104: Uncaught NullPointerException I wonder if I placed the code on the right place, or I did something wrong with ksoap2??
here is the code for web service
namespace VoiceServer
{
/// <summary>
/// Converting AMR to WAV
/// </summary>
[WebService(Namespace = "http://tempuri.org/")]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
[System.ComponentModel.ToolboxItem(false)]
public class Service1 : System.Web.Services.WebService
{
public string UploadFile(String receivedByte, String location, String fileName)
{
String filepath = fileName;
/*don't worry about receivedByte and location, I will work on them after the problem is solved :) */
return "Success"+filepath;
}
private void InitializeComponent()
{
}
}
}
Below is the code running on Eclipse, I'm not sure if I placed the code for sending file to web service on the right place.
public class MyAudio extends MainScreen {
private ButtonField _startRecordingButton;
private ButtonField _stopRecordingButton;
private HorizontalFieldManager _fieldManagerButtons;
private VoiceNotesRecorderThread _voiceRecorder;
private LabelField _myAudioTextField;
private DateField hourMin;
private long _initTime;
public MyAudio() {
_startRecordingButton = new ButtonField("Speak!", ButtonField.CONSUME_CLICK);
_stopRecordingButton = new ButtonField("Stop!", ButtonField.CONSUME_CLICK);
_fieldManagerButtons = new HorizontalFieldManager();
_voiceRecorder = new VoiceNotesRecorderThread(500000,"file:///store/home/user/voicefile.amr",this);
_voiceRecorder.start();
myButtonFieldChangeListener buttonFieldChangeListener = new myButtonFieldChangeListener();
_startRecordingButton.setChangeListener(buttonFieldChangeListener);
_stopRecordingButton.setChangeListener(buttonFieldChangeListener);
_fieldManagerButtons.add(_startRecordingButton);
_fieldManagerButtons.add(_stopRecordingButton);
_myAudioTextField = new LabelField(" Welcome to VoiceSMS!!!" );
add(_fieldManagerButtons);
add(_myAudioTextField);
SimpleDateFormat sdF = new SimpleDateFormat("ss");
hourMin = new DateField("", 0, sdF);
hourMin.setEditable(false);
hourMin.select(false);
_initTime = System.currentTimeMillis();
add(hourMin);
}
public void setAudioTextField(String text) {
_myAudioTextField.setText(text);
}
public void startTime() {
_initTime = System.currentTimeMillis();
hourMin.setDate(0);
}
public void updateTime() {
hourMin.setDate((System.currentTimeMillis()-_initTime));
}
class myButtonFieldChangeListener implements FieldChangeListener{
public void fieldChanged(Field field, int context) {
if(field == _startRecordingButton) {
try {
_voiceRecorder.startRecording();
} catch (IOException e) {
e.printStackTrace();
}
}else if(field == _stopRecordingButton) {
_voiceRecorder.stopRecording();
//----------Send AMR to Web Service-------------//
Object response = null;
String URL = "http://http://localhost:portnumber/Service1.asmx";
String method = "UploadFile";
String NameSpace = "http://tempuri.org/";
FileConnection fc = null;
byte [] ary = null;
try
{
fc = (FileConnection)Connector.open("file:///store/home/user/voicefile.amr",Connector.READ_WRITE);
int size = (int) fc.fileSize();
//String a = Integer.toString(size);
//Dialog.alert(a);
ary = new byte[size];
fc.openDataInputStream().read(ary);
fc.close();
}
catch (IOException e1)
{
e1.printStackTrace();
}
SoapObject client = new SoapObject(NameSpace,method);
client.addProperty("receivedByte",new SoapPrimitive(SoapEnvelope.ENC,"base64",Base64.encode(ary)));
client.addProperty("location","Test/");
client.addProperty("fileName","file:///store/home/user/voicefile.amr");
SoapSerializationEnvelope envelope = new SoapSerializationEnvelope(SoapEnvelope.VER11);
envelope.bodyOut = client;
HttpTransport http = new HttpTransport(URL);
try
{
http.call(method,envelope);
}
catch(InterruptedIOException io)
{
io.printStackTrace();
}
catch (IOException e)
{
System.err.println(e);
}
catch (XmlPullParserException e)
{
System.err.println(e);
}
catch(OutOfMemoryError e)
{
System.out.println(e.getMessage());
}
catch(Exception e)
{
e.printStackTrace();
}
try
{
response = envelope.getResponse();
Dialog.alert(response.toString());
}
catch (SoapFault e)
{
System.err.println(e);
System.out.println("Soap Fault");
}
catch(NullPointerException ne)
{
System.err.println(ne);
}
Dialog.alert(response.toString());
//Dialog.alert("Send Success");
//----------End of Upload-to-Web-Service--------//
}
}
}
}
I don't know if the file is not sent to web service, or web service has got the file and produce no response??? I am a real newbie for BB programming. Please let me know if I did anything wrong.
Thanks in advance!!!
There is a typo in your URL variable value.
"http://" typed twice
String URL = "http://http://localhost:portnumber/Service1.asmx";
Hooray!!! Problem Solved!
just changed URL as Rafael suggested and added [WebMethod] above "public string UploadFile" in the web service code