Showing posts with label web-services. Show all posts
Showing posts with label web-services. Show all posts

Thursday, June 21, 2018

java - Set content type on a soap service

Leave a Comment

Can someone please tell me how can I set the content type for a soap service in java?I want to set the content type as "multipart/related". I searched trough a lot of question but I cannot figure it out how can I do it.

I have something like this:

The proxy class:

@WebService(name = "DocumentManagementForUnderwritingService",targetNamespace = "myNameSpace") @SOAPBinding(parameterStyle = SOAPBinding.ParameterStyle.BARE) @XmlSeeAlso({    //some other classes }) public interface DocumentManagementForUnderwritingService {    @WebMethod     @WebResult(name = "uploadDocumentResponse", targetNamespace = "myNameSpace", partName = "Body")     public UploadDocumentResponse uploadDocument(@WebParam(name = "uploadDocumentRequest", targetNamespace = ""myNameSpace", partName = "Body")     UploadDocumentRequest body) throws ServiceException, SystemException ; 

}

Request Class

@XmlAccessorType(XmlAccessType.FIELD) @XmlType(name = "uploadDocumentRequest", propOrder = {     "positionId",     "username",     "documentItemId",     "documentCod"     })     public class UploadDocumentRequest {      @XmlElement(required = true)     protected String positionId;     @XmlElement(required = true)     protected String username;     protected String documentItemId;     protected String documentCod;      //setters & getters  } 

In the class who calls the service (and I think here I have to set somehow the content type)

 BindingProvider bp = (BindingProvider) proxy;   UploadDocumentRequest request = new UploadDocumentRequest();   request.setDocumentItemId(input.getDocumentItemId());   request.setPositionId(input.getPositionId());  UploadDocumentResponse response = proxy.uploadDocument(request); 

I also chained a handler where I'm trying to set the Mime_type and adding an attachment:

private Static final String MULTIPART_MYME_TYPE="multipart/related";   @Override     public boolean handleMessage(SOAPMessageContext context) {         Boolean isRequest = (Boolean) context.get(MessageContext.MESSAGE_OUTBOUND_PROPERTY);          try {              if (isRequest) {                  if (context.containsKey("pdf")) {                     byte[] arr = (byte[]) context.get("pdf");                      SOAPMessage soapMsg = context.getMessage();                     soapMsg.getMimeHeaders().addHeader("Content-type", MULTIPART_MIME_TYPE);                     AttachmentPart attachment = createAttachment(soapMsg, arr, "test.pdf", context);                     soapMsg.addAttachmentPart(attachment);                     Iterator<AttachmentPart> it = context.getMessage().getAttachments();                     while (it.hasNext()) {                         AttachmentPart att = it.next();                         System.out.println(att.getContent());                     }                     System.out.println("ok");                 }             }         } catch (Exception e) {             return false;         }          return true;      }    private AttachmentPart createAttachment(SOAPMessage msg, byte[] payload, String fileId, SOAPMessageContext context) {          @SuppressWarnings("unchecked")         Map<String, DataHandler> attachmentsMap = (Map<String, DataHandler>) context.get(MessageContext.OUTBOUND_MESSAGE_ATTACHMENTS);           ByteArrayDataSource ds = new ByteArrayDataSource(payload, MULTIPART_MIME_TYPE);         DataHandler dh = new DataHandler(ds);          AttachmentPart attachmentPart = msg.createAttachmentPart();          attachmentPart.setContent(new ByteArrayInputStream(payload), MULTIPART_MIME_TYPE);         attachmentPart.setContentId(fileId);          String contentDisposition = "Content-Disposition: attachment; name=\"" + fileId + "\"";         attachmentPart.addMimeHeader("Content-Disposition", contentDisposition);          msg.addAttachmentPart(attachmentPart);          attachmentsMap.put(fileId, dh);          context.put(MessageContext.OUTBOUND_MESSAGE_ATTACHMENTS, attachmentsMap);          context.getMessage().getAttachments();          return attachmentPart;     } 

Thank you in advance!

1 Answers

Answers 1

Cast the binding to a SOAPBinding and there is a flag to enable MTOM.

import javax.xml.ws.soap.SOAPBinding;  BindingProvider bp = (BindingProvider) proxy;  // Set binding and MTOM SOAPBinding binding = (SOAPBinding) bp.getBinding(); binding.setMTOMEnabled(true); 
Read More

Monday, May 7, 2018

Can't access public class from web service

Leave a Comment

I have a very weird scenario which I can't seem to figure out what's going on. I have a web service which is written in C# and the target framework is 3.5. I have many Classes and Methods but for simplicity I will make use of only two classes in the question.

public class PathNames {    private string _pathA = "Some Path";    private string _pathB = "Another Path";    public string BaseDirectoryPath    {         get         {             return Path.Combine(_pathA, _pathB);          }    } } 

The second class is as follows:

public class UserInformation {    public string UserName { get; set; }    ...//more properties  } 

Both of the above classes are in the same namespace.

The web service is referenced in a WebForm Application with the target framework being 4.0. Everything seems to be working fine and I can see the UserInformation class when I view it in Object Browser. However the PathNames class does not seem to be visible in the Object Broswer.

Both of the source files in question are set to Compile in the File Properties windows. I have 5 classes similar to that of UserInformation and same settings in the File Properties window where they are just simple POCO and only have public auto propteries. These all seem to be coming through and I can access them and see them in the Object Browser. For some strange reason I cannot PathNames class to come through. I have tried to add some new dummy classes and have the same issue as PathNames class. Can someone tell me what I am doing wrong please.

  1. The web service old ASMX

  2. Web service client is being created through VS add service reference

  3. Using VS 2017 pro - version 15.6.7.

  4. After publish if I de-compile the dll then the PathNames class is there. So it's clearly in the dll.

  5. I have look at this but still no luck.

3 Answers

Answers 1

Using Data Contracts in web service

Service can't expose private/read-only properties. DataMember attribute is used for marking public members or properties (with public getter and setter) of class marked with DataContract attribute. DataContract can be used as parameter or return value of operation.

Windows Communication Foundation (WCF) uses a serialization engine called the Data Contract Serializer by default to serialize and deserialize data (convert it to and from XML), and XML serialization (by default) doesn't serialize read=only properties.

For More Information you can read the MS Docs for Data Contracts :- https://docs.microsoft.com/en-us/dotnet/framework/wcf/feature-details/using-data-contracts

To understand the various Limitation of Data Contracts please refer : -https://docs.microsoft.com/en-us/dotnet/framework/wcf/feature-details/types-supported-by-the-data-contract-serializer

Solution :

Anyway. What are you trying to do? Exposing properties means that you expect some stateful behavior. If you going to use this property in operation contract, which is seems to be, then you you must define the properties with public getter and setter so it can be serialized.

As the @Nikosi stated in previous answer, you have to define public setter for your BaseDirectoryPath property.

Answers 2

The only difference based on the example provided that one property is readonly while the other can be modified.

In order to make the class serializable consider rafactoring the property

public class PathNames {     private string _pathA = "Some Path";     private string _pathB = "Another Path";      public PathNames() {         BaseDirectoryPath = Path.Combine(_pathA, _pathB);     }      public string BaseDirectoryPath { get; set; } } 

You can use a default constructor to set the default value of the property

or just have an empty setter on the property

public class PathNames {     private string _pathA = "Some Path";     private string _pathB = "Another Path";      public string BaseDirectoryPath {          get {             return Path.Combine(_pathA, _pathB);         }         set {             //No OP         }     } } 

Answers 3

You can see how creating a Custom ASP.NET Web Service. Might you need to rebuild web service ASP.Net and add your assembly to the global assembly cache (GAC).

I hope this help you.

Read More

Friday, March 23, 2018

Handling Status Dilemma

Leave a Comment

There is a recurring problem regarding status fields and similar predefined set of values.

Let's take an example of an ordering system with an order entity which has a status that could be New, In Progress, Paid, etc.

The problem:

The Status of an order need to be

  • stored (in database)
  • processed (in backend)
  • communicated (to frontend in web service API)

How to do these three activities while keeping:

  • Preserve the meaning of the status.
  • efficient storage.

Here are some example implementations with their pros and cons:

1- Status Table

  • The database will contain a status table with id, name
  • Order table references the id of the status.

    CREATE TABLE `status` (   `id` INT NOT NULL,   `name` VARCHAR(45) NOT NULL,   PRIMARY KEY (`id`));  CREATE TABLE IF NOT EXISTS `order` (   `id` INT NOT NULL AUTOINCREMENT,   `status_id` INT NOT NULL,   PRIMARY KEY (`id`),   INDEX `order_status_idx` (`status` ASC),   CONSTRAINT `order_status_id`     FOREIGN KEY (`status_id`)     REFERENCES `status` (`id`)     ON DELETE NO ACTION     ON UPDATE NO ACTION); 
  • The backend code has an enum that gives these predefined integers a meaning in the code

    enum Status {     PAID = 7; };  // While processing as action ... order.status = Status::PAID; 
  • The web service API will return the status number

    order: { id: 1, status_id: 7 } 
  • The frontend code has a similar enum that gives these predefined integers a meaning in the code. (like the backend code)

  • Pros:

    • The database is well defined and normalized
  • Cons:
    • The mapping between the status number and meaning is done in three places which gives space for human errors and inconsistency in defining the meaning of a specific status number.
    • The returned data from the API is not descriptive because status_id: 7 does not deliver a concrete meaning because it does not include the meaning of the status_id: 7

2- Status ENUM

  • In database, the order table will contain a status columns with type ENUM containing the predefined statuses.

    CREATE TABLE IF NOT EXISTS `order` (   `id` INT NOT NULL AUTOINCREMENT,   `status` ENUM('PAID') NULL,   PRIMARY KEY (`id`)); 
  • The backend code has constant values as code artifacts for the predefined status

    enum Status {     PAID = 'PAID' }; 

    OR

    class Status { public:     static const string PAID = PAID; }; 

    To Be used as follwoing

    // While processing as action ... order.status = Status::PAID; 
  • The web service API will return the status constant

    order: { id: 1, status: 'PAID' } 
  • The frontend code will have a similar construct for predefined status constants. (like the backend code)

  • Pros:

    • The database is well defined and normalized
    • The returned data from the API is descriptive and deliver the required meaning.
    • The status constants used already contain their meaning which reduces the chances of errors.
  • Cons:
    • Using an ENUM type for a column in database has its limitations. Adding a new status constant to that enum later using an ALTER command is expensive specially for huge tables like order table.

3- My proposed solution:

  • The database will contain a status table with one field called key with type string which is the primary key of this table.

    CREATE TABLE `status` (   `key` VARCHAR(45) NOT NULL,   PRIMARY KEY (`key`)); 
  • The order table will contain a field called status with type string which references the key field of the status table.

    CREATE TABLE IF NOT EXISTS `order` (   `id` INT NOT NULL AUTOINCREMENT,   `status` VARCHAR(45) NOT NULL,   PRIMARY KEY (`id`),   INDEX `order_status_idx` (`status` ASC),   CONSTRAINT `order_status`     FOREIGN KEY (`status`)     REFERENCES `status` (`key`)     ON DELETE NO ACTION     ON UPDATE NO ACTION); 
  • The backend code has constant values as code artifacts for the predefined status

    enum Status {     PAID = 'PAID' }; 

    OR

    class Status { public:     static const string PAID = PAID; }; 

    To Be used as follwoing

    // While processing as action ... order.status = Status::PAID; 
  • The web service API will return the status constant

    order: { id: 1, status: 'PAID' } 
  • The frontend code will have a similar construct for predefined status constants. (like the backend code)

  • Pros:

    • The database is well defined and normalized
    • The returned data from the API is descriptive and deliver the required meaning.
    • The status constants used already contain their meaning which reduces the chances of errors.
    • Adding a new status constant is simple with INSERT command in the status table.
  • Cons:
    • ???

I'd like to know if this is a feasible solution or there is a better solution for this recurring problem.

Please include reasons why the proposed solution is bad and why your better solution is better

Thank you.

1 Answers

Answers 1

This my approach for this problem:

  1. I add a column status with type string in the orders table.
  2. Define the constant of all your statuses in your class so you can reference them easily.
  3. Make a validation rule on creation of order that the status value is in the only allowed ones you defines earlier.

This makes adding a new status very easily by just editing your code base, and the retrieved value for the status is still a string (descriptive).

I hope this answer your question.

Read More

Tuesday, February 20, 2018

Can ASP.NET SOAP XML web services run on Azure?

Leave a Comment

We have a large number of legacy ASP.NET SOAP XML web services in our software system. We normally host these in IIS. I would like to know if these can be hosted on Azure with no or as little change as possible? The web services are all written in C#.

Our client is looking at using "full" Azure, not just running these in a VM in Windows using IIS on Azure.

Are there any "best practices" on "porting" ASP.NET SOAP XML web services to Azure?

1 Answers

Answers 1

Configure the XML Web service to use Windows authentication, using IIS. IIS allows you to specify security at either the directory or file level. If you want to specify the security for an XML Web service on a per-file basis, set the permissions for the XML Web service on the .asmx file in IIS. The .asmx file is the entry point into the XML Web service. See the IIS documentation for details.

Modify the configuration file to specify Windows authentication. Set the mode attribute of the authentication XML element in a configuration file to "Windows". For details on how to configure a configuration file, see ASP.NET Configuration.

Read More

Wednesday, February 14, 2018

Exe as Webservice Endpoint

Leave a Comment

I got a webservice endpoint and I stumple upon how to correctly implement it. It seems to be an parameterized exe-file which returns an XML Reply. There is no documentation.

I am used to soap, wcf and rest but this is completely unknown to me, has anyone a guide or a best case how to implement such a service? I can consume it with a HTTP GET but there are some questions left to me:

I know the questions are quite broad... But I could not find anything about it in the interwebz.

  • Is there a secure way to publish exe files as webservice?
  • Are there any critical downsides implementing such an interface?
  • Make I myself a fool and this is just an alias?

Example Url: http://very.exhausting.company/Version/SuperStrange.exe?parameter=String

1 Answers

Answers 1

Web servers

What you call a webservice endpoint is nothing else than a web server listening on some host (normally 0.0.0.0) and some port on a physical or virtual machine and responding with some HTTP response to HTTP requests sent to that host, port and URIs that the web server cares to process.

Any web server is itself an application or a static or dynamic component of an application as the following examples illustrate:

  • JBoss, Glassfish, Tomcat etc. are applications, known as application servers, into which containers/servlets/plugins implementing web servers and corresponding endpoints are deployed. These listen on some port exposing generic web servers routing requests to those containers and their servlets;
  • a fat jar started with java -jar on a JVM which deploys a vert.x verticle featuring a vert.x HttpServer listening on some port is nothing else than a web server;
  • an interpreter such as node.js parsing and executing JavaScript code based on the express module will most likely deploy a web server on some port;
  • finally, a statically or dynamically linked application written in languages such as C++ or Go can expose a web server listing on some port.

All of the above cases feature different deployment mechanisms, but what they deploy is essentially the same: a piece of software that listens for HTTP requests on some port, executes some logic based on request and returns HTTP responses to the caller.

Your windows exe file is most likely a statically linked application that provides a web server.

Protocols

So we know you have a web server as it reacts to an HTTP GET. How does it relate to REST, SOAP etc? Effectively, REST, SOAP etc are higher level protocols. TCP is the low level, HTTP is based on top of that and your server supports that. REST, SOAP and everything else that you mention are higher level protocols that are based, among others, on HTTP. So all you know is that your application (web server) supports HTTP, but you do not know which higher level data exchange protocol it implements. It definitely implements some, at least a custom one that its author came up with to exchange data between a client and this application.

You can try to reverse engineer it, but it is not clear how would you find out about all possible endpoints, arguments, payload structures, accepted headers etc. Essentially, you have a web server publishing some sort of an API, but there is no generic way of telling what that API is.

Security

The world around you does not have to know how the API is published. You can put any of the above 4 web server implementations behind exactly the same firewall or a reverse proxy with SSL termination exposing just one host and port over SSL. So there is no difference in security, with respect to the world, whether you deploy it as exe or as a war into JBoss. This is not to say, that your exe file is secure: depending on how it is implemented it may allow all sorts of attacks, but again, this is equally true for any mechanism.

Read More

Wednesday, December 27, 2017

WCF : The EncryptedKey clause was not wrapped with the required encryption token 'System.IdentityModel.Tokens.X509SecurityToken'

Leave a Comment

I'm trying to use WCF client to connect to Java based web services

Certificates I have been provided (self-signed) work perfectly in SOAPUI.

Here is my setup:

enter image description here

enter image description here

enter image description here

enter image description here

enter image description here

enter image description here

However, I'm having problems using WCF client.

My app.config

    <bindings>       <customBinding>         <binding name="Example_TestBinding">                        <security defaultAlgorithmSuite="TripleDesRsa15"                      authenticationMode="MutualCertificate"                      requireDerivedKeys="false"                      includeTimestamp="false"                      messageProtectionOrder="SignBeforeEncrypt"                      messageSecurityVersion="WSSecurity10WSTrust13WSSecureConversation13WSSecurityPolicy12BasicSecurityProfile10"                      requireSignatureConfirmation="false">                             <localClientSettings detectReplays="true"/>             <localServiceSettings detectReplays="true"/>                           </security>                         <textMessageEncoding messageVersion="Soap11"/>                        <httpsTransport authenticationScheme="Basic" manualAddressing="false" maxReceivedMessageSize="524288000" transferMode="Buffered"/>                     </binding>       </customBinding>     </bindings>   <client>     <endpoint        address="https://blabla.hana.ondemand.com/Example_Test"        binding="customBinding"        bindingConfiguration="Example_TestBinding"        contract="WebServiceTest.Example_Test"        name="Example_Test"      />   </client> 

Using Keystore Explorer I export both certificates from JKS as:

  • public_test_hci_cert.cer
  • test_soap_ui.p12

Web service call:

            var client = new Example_TestClient();             client.ClientCredentials.UserName.UserName = "user";             client.ClientCredentials.UserName.Password = "pass";              X509Certificate2 certClient = new X509Certificate2(certClientPath, certClientPassword);             client.ClientCredentials.ClientCertificate.Certificate = certClient;              X509Certificate2 certService= new X509Certificate2(certServicePath);             client.ClientCredentials.ServiceCertificate.DefaultCertificate = certService;              var response = client.Example_Test(requestObj);   

The request arrives perfectly at the server but it seems that WCF doesn't understand the response since I get this exception:

"The EncryptedKey clause was not wrapped with the required  encryption token 'System.IdentityModel.Tokens.X509SecurityToken'."     at System.ServiceModel.Security.WSSecurityJan2004.WrappedKeyTokenEntry.CreateWrappedKeyToken(String id, String encryptionMethod, String carriedKeyName, SecurityKeyIdentifier unwrappingTokenIdentifier, Byte[] wrappedKey, SecurityTokenResolver tokenResolver)\r\n ... 

Service Trace gives:

The security protocol cannot verify the incoming message 

UPDATE1: simplified the task by using the same certificate for signing and encryption. Same message.

UPDATE2: I wrote CustomTextMessageEncoder where I manually decrypt the message body and it works. However returning it in ReadMessage still throws the error.

    public override Message ReadMessage(ArraySegment<byte> buffer, BufferManager bufferManager, string contentType)     {         var msgContents = new byte[buffer.Count];         Array.Copy(buffer.Array, buffer.Offset, msgContents, 0, msgContents.Length);         bufferManager.ReturnBuffer(buffer.Array);         var message = Encoding.UTF8.GetString(msgContents);          //return ReadMessage(Decryptor.DecryptBody(message), int.MaxValue);         var stream = new MemoryStream(Encoding.UTF8.GetBytes(message));         return ReadMessage(stream, int.MaxValue);     }      public static MemoryStream DecryptBody(string xmlResponse)     {         X509Certificate2 cert = new X509Certificate2(clientCertPath, certPass);         SymmetricAlgorithm algorithm = new TripleDESCryptoServiceProvider();          XmlDocument xmlDoc = new XmlDocument();         xmlDoc.PreserveWhitespace = true;         xmlDoc.LoadXml(xmlResponse);          XmlElement encryptedKeyElement = xmlDoc.GetElementsByTagName("EncryptedKey", XmlEncryptionStrings.Namespace)[0] as XmlElement;         XmlElement keyCipherValueElement = encryptedKeyElement.GetElementsByTagName("CipherValue", XmlEncryptionStrings.Namespace)[0] as XmlElement;         XmlElement encryptedElement = xmlDoc.GetElementsByTagName("EncryptedData", XmlEncryptionStrings.Namespace)[0] as XmlElement;          var key = Convert.FromBase64String(keyCipherValueElement.InnerText);          EncryptedData edElement = new EncryptedData();         edElement.LoadXml(encryptedElement);         EncryptedXml exml = new EncryptedXml();          algorithm.Key = (cert.PrivateKey as RSACryptoServiceProvider).Decrypt(key, false);          byte[] rgbOutput = exml.DecryptData(edElement, algorithm);         exml.ReplaceData(encryptedElement, rgbOutput);          //var body = Encoding.UTF8.GetString(rgbOutput);          MemoryStream ms = new MemoryStream();         xmlDoc.Save(ms);         return ms;     }  

1 Answers

Answers 1

I left this problem for the final sprint in my project and finally got back to it.
It is certificate problem. The self-signed certificates I was provided by Java based web service was generated with KeyStore Explorer. Both certificates were missing an important part:

Subject Key Identifier 

enter image description here

Once regenerated WCF was able to decrypt it without using encoders.

Also I had to:

  1. Install service certificate in the Trusted Root CA (user)
  2. Set Web Services to reply with Timestamp

I removed all config from the code (except client username and password) and placed in the app.config. Here is the complete config:

  <system.serviceModel>       <bindings>           <customBinding>             <binding name="Example_TestBinding">                            <security                                                 defaultAlgorithmSuite="TripleDesRsa15"                          authenticationMode="MutualCertificate"                          requireDerivedKeys="false"                          includeTimestamp="true"                          messageProtectionOrder="SignBeforeEncrypt"                          messageSecurityVersion="WSSecurity10WSTrustFebruary2005WSSecureConversationFebruary2005WSSecurityPolicy11BasicSecurityProfile10"                          requireSignatureConfirmation="false"                         allowSerializedSigningTokenOnReply="true"                          >               </security>                             <textMessageEncoding messageVersion="Soap11"/>               <httpsTransport authenticationScheme="Basic"                                manualAddressing="false"                                maxReceivedMessageSize="524288000"                                transferMode="Buffered"/>                                       </binding>           </customBinding>          </bindings>       <client>         <endpoint address="https://klaatuveratanecto.com/cxf/Example_TestBinding"                   behaviorConfiguration="endpointCredentialBehavior"                   binding="customBinding"                    bindingConfiguration="Example_TestBinding"                    contract="WebServiceTest.Example_Test"                    name="Example_Test">           <identity>             <dns value="test.service.klaatuveratanecto.com"/>           </identity>         </endpoint>       </client>     <behaviors>       <endpointBehaviors>         <behavior name="endpointCredentialBehavior">           <clientCredentials>             <serviceCertificate>               <defaultCertificate findValue="test.service.klaatuveratanecto.com"                                storeLocation="CurrentUser"                                storeName="Root"                                x509FindType="FindBySubjectName" />             </serviceCertificate>             <clientCertificate findValue="test.client.klaatuveratanecto.com"                                storeLocation="CurrentUser"                                storeName="My"                                x509FindType="FindBySubjectName" />           </clientCredentials>         </behavior>       </endpointBehaviors>     </behaviors>   </system.serviceModel> 

How did I get there. Well looking at the stack trace:

Server stack trace:     at System.ServiceModel.Security.WSSecurityJan2004.WrappedKeyTokenEntry.CreateWrappedKeyToken(String id, String encryptionMethod, String carriedKeyName, SecurityKeyIdentifier unwrappingTokenIdentifier, Byte[] wrappedKey, SecurityTokenResolver tokenResolver)    at System.ServiceModel.Security.WSSecurityJan2004.WrappedKeyTokenEntry.ReadTokenCore(XmlDictionaryReader reader, SecurityTokenResolver tokenResolver)    at System.ServiceModel.Security.WSSecurityTokenSerializer.ReadTokenCore(XmlReader reader, SecurityTokenResolver tokenResolver)    at System.IdentityModel.Selectors.SecurityTokenSerializer.ReadToken(XmlReader reader, SecurityTokenResolver tokenResolver)    at System.ServiceModel.Security.WSSecurityOneDotZeroReceiveSecurityHeader.DecryptWrappedKey(XmlDictionaryReader reader)    at System.ServiceModel.Security.ReceiveSecurityHeader.ReadEncryptedKey(XmlDictionaryReader reader, Boolean processReferenceListIfPresent)    at System.ServiceModel.Security.ReceiveSecurityHeader.ExecuteFullPass(XmlDictionaryReader reader)    at System.ServiceModel.Security.StrictModeSecurityHeaderElementInferenceEngine.ExecuteProcessingPasses(ReceiveSecurityHeader securityHeader, XmlDictionaryReader reader)    at System.ServiceModel.Security.ReceiveSecurityHeader.Process(TimeSpan timeout, ChannelBinding channelBinding, ExtendedProtectionPolicy extendedProtectionPolicy)    at System.ServiceModel.Security.MessageSecurityProtocol.ProcessSecurityHeader(ReceiveSecurityHeader securityHeader, Message& message, SecurityToken requiredSigningToken, TimeSpan timeout, SecurityProtocolCorrelationState[] correlationStates)    at System.ServiceModel.Security.AsymmetricSecurityProtocol.VerifyIncomingMessageCore(Message& message, String actor, TimeSpan timeout, SecurityProtocolCorrelationState[] correlationStates)    at System.ServiceModel.Security.MessageSecurityProtocol.VerifyIncomingMessage(Message& message, TimeSpan timeout, SecurityProtocolCorrelationState[] correlationStates)    at System.ServiceModel.Channels.SecurityChannelFactory`1.SecurityRequestChannel.ProcessReply(Message reply, SecurityProtocolCorrelationState correlationState, TimeSpan timeout)    at System.ServiceModel.Channels.SecurityChannelFactory`1.SecurityRequestChannel.Request(Message message, TimeSpan timeout)    at System.ServiceModel.Dispatcher.RequestChannelBinder.Request(Message message, TimeSpan timeout)    at System.ServiceModel.Channels.ServiceChannel.Call(String action, Boolean oneway, ProxyOperationRuntime operation, Object[] ins, Object[] outs, TimeSpan timeout)    at System.ServiceModel.Channels.ServiceChannelProxy.InvokeService(IMethodCallMessage methodCall, ProxyOperationRuntime operation)    at System.ServiceModel.Channels.ServiceChannelProxy.Invoke(IMessage message) 

I debugged CreateWrappedKeyToken method with help of JetBrains dotPeek and saw that it tries to read raw SKI from the certificate and it's not finding it.

Read More

Sunday, December 10, 2017

https PHP/MySql webservice with ios instagram login

Leave a Comment

I'm trying to wrap my mind around something. I want to create a web service that accesses a database from an ios/ android app. Now I want the user to be able to log into the app through the Instagram API.

I'm a bit confused as in how they tie together. Obviously step one is to login with Instagram. What do I do then? I would like to save this user information I receive (let's say at least the username/ID) to the database with some other info that don't come from Instagram, like the location. All that in a secure way. can i use the instagram token for this? I'm a bit stuck on this process...

2 Answers

Answers 1

To do what you're looking for, the easiest way is to do a Rest WebService.

Using this WebService, both your iOS and Android apps will be able to connect and send/get data.

Your WebService should be responsible for managing all the data, saving or getting info from a Database. And can be also be responsible for user authentication.

To talk to your WebService, your app can use JSON. So you should learn how to send and parse JSON.

Good Luck!

Useful links:

Instagram's API

Instagram Integration in Android Application Tutorial

UPDATE

To correlate the instagram user with your database you can use the provided user id:

{     "access_token": "fb2e77d.47a0479900504cb3ab4a1f626d174d2d",     "user": {         "id": "1574083",         "username": "snoopdogg",         "full_name": "Snoop Dogg",         "profile_picture": "..."     } } 

See: Instagram Authentication

Answers 2

After you complete the step 3 Instagram Autorization, which is pretty simple and i wont talk about it since you question is how to integrate Instagram data with you database, you should receive the following json:

{     "access_token": "fb2e77d.47a0479900504cb3ab4a1f626d174d2d",     "user": {         "id": "1574083",         "username": "snoopdogg",         "full_name": "Snoop Dogg",         "profile_picture": "..."     } } 

What you do with the data is a matter of architeture:

1) You user may authorize through instagram or regular username/password

Create a user table that has both password field and instagram user_id:

Your user table might be like:

CREATE TABLE users (     id INT AUTO_INCREMENT NOT NULL ,     username VARCHAR(255) NOT NULL,     password VARCHAR(255) DEFAULT NULL,     instagram_userid INT DEFAULT NULL,     instagram_accesstoken VARCHAR(255) DEFAULT NULL,     PRIMARY KEY(id) ); 

Anytime a user authenticates through Instagram you should:

  1. Look for you uses table for a row with the same instagram_userid returned by instagram api.
  2. If the instagram_userid already exists, you should authenticate you user in YOUR application now (for example, using SESSIONS/COOKIES, i.e. the usual way you have done your whole life).
  3. If the instagram_userid doesnt exist, you should create a user row, with the username returned by Instagram API. Also authenticate this user with SESSION.

2)Instagram is your only user choice for authenticating

You should then just create a user table that is only a mirror for instagram api return. You can treat instagram_userid as your primary key:

CREATE TABLE users (     username VARCHAR(255) NOT NULL,     instagram_userid INT DEFAULT NULL,     instagram_accesstoken VARCHAR(255) DEFAULT NULL,     PRIMARY KEY(instagram_userid)  ); 
  1. Anytime a user authenticates throught Instagram API, you should search in you user table for a row with the same id as returned by Instagram API.
  2. If the row exists, authenticate that user in your application.
  3. If the row doesnt exist, create it and authenticate the user.

Account merging

If your application handles both username/passoword authentication and maybe others authentication providers , you should expect that a user might forget that he registered through you app with lets way Instagram Auth, and try to autenticate through username/password. If this happens, you might provide a way to merge the accounts, instead of duplicating it. For example, if the user Instagram email exists in your database as a username, you should update this row with instagram api data, instead of assuming its a new account. In this way, now your user can authenticate both with usuername/password and Instagram.

Access token

The instagram access token is stored, but now used. Why? Because it would be used for fetching instagram data, like user posts, friends list, etc. If you want to do it, you should not assume the token is valid, because it might expire, so you should handle token expiration and provide a way to the user authenticate again.

Read More

Sunday, December 3, 2017

Top-down Web Service Generation using AXIS1 is taking my complexType apart

Leave a Comment

This is my entire WSDL:

<?xml version="1.0" encoding="utf-8"?> <definitions    name="TokenService"                  targetNamespace="urn:mace:ideas:TokenNamespace"                 xmlns="http://schemas.xmlsoap.org/wsdl/"                  xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"                 xmlns:tns="urn:mace:ideas:TokenNamespace"                  xmlns:xsd="http://www.w3.org/2001/XMLSchema">     <types>         <xs:schema  targetNamespace="urn:mace:ideas:TokenNamespace"                     version="1.0"                      xmlns:tns="urn:mace:ideas:TokenNamespace"                      xmlns:xs="http://www.w3.org/2001/XMLSchema">              <!-- A single HTTP header -->             <xs:complexType name="httpHeader">                 <xs:sequence>                  <xs:element name="Content" type="xs:string" />                  <xs:element name="Usage">                    <xs:simpleType>                      <xs:restriction base="xs:string">                        <xs:enumeration value="new" id="new" />                        <xs:enumeration value="always" id="always" />                        <xs:enumeration value="once" id="once" />                      </xs:restriction>                    </xs:simpleType>                  </xs:element>                 </xs:sequence>             </xs:complexType>                    <!-- A list of HTTP headers -->             <xs:complexType name="httpHeaders">                 <xs:sequence>                     <xs:element name="httpHeader" type="tns:httpHeader" minOccurs="0" maxOccurs="unbounded"/>                 </xs:sequence>             </xs:complexType>              <!-- EACommand Id -->             <xs:simpleType name="EACommandId">                 <xs:restriction base="xs:string">                     <xs:enumeration value="ReadDG" />                     <xs:enumeration value="ReadRD" />                     <xs:enumeration value="WriteRD" />                     <xs:enumeration value="VerifyData" />                     <xs:enumeration value="CheckAge" />                 </xs:restriction>             </xs:simpleType>                              <!-- EACommand operator -->             <xs:simpleType name="EACommandOperator">                 <xs:restriction base="xs:string">                     <xs:enumeration value="equal" />                     <xs:enumeration value="less" />                     <xs:enumeration value="greater" />                 </xs:restriction>             </xs:simpleType>                              <!-- EACommand -->             <xs:complexType name="EACommand">                 <xs:sequence>                     <xs:element minOccurs="1" maxOccurs="1" name="EACommandId" type="tns:EACommandId" />                     <xs:element minOccurs="0" maxOccurs="1" name="dataId" type="xs:integer" />                     <xs:element minOccurs="0" maxOccurs="1" name="EACommandOperator" type="tns:EACommandOperator" />                     <xs:element minOccurs="0" maxOccurs="1" name="value" type="xs:string" />                 </xs:sequence>             </xs:complexType>              <!-- Batch command -->             <xs:complexType name="batchCommand">                 <xs:sequence>                     <xs:element name="stopOnAnyError" type="xs:boolean" nillable="false" />                     <xs:element minOccurs="0" maxOccurs="unbounded" name="command" type="tns:EACommand" />                 </xs:sequence>             </xs:complexType>                    <!-- TokenRequest -->             <xs:complexType name="tokenRequest">                 <xs:sequence>                     <xs:element minOccurs="1" name="raCode" type="xs:string" />                     <xs:element minOccurs="1" name="appRefId" type="xs:string" />                     <xs:element minOccurs="1" name="deptCode" type="xs:string" />                     <xs:element minOccurs="1" name="raArtifactReceiverURL" type="xs:string" />                     <xs:element minOccurs="1" name="target" type="xs:string" />                     <xs:element minOccurs="0" name="dvnHash" type="xs:string" />                     <xs:element minOccurs="0" name="msgHash" type="xs:string" />                     <xs:element minOccurs="0" name="spinAction" type="xs:string" />                     <xs:element minOccurs="0" name="locale" type="xs:string" />                     <xs:element minOccurs="0" name="termsAndConditions" type="xs:string" />                     <xs:element minOccurs="0" name="removeCard" type="xs:string" />                     <xs:element minOccurs="0" name="reader" type="xs:string" />                 </xs:sequence>             </xs:complexType>              <!-- GetToken, a wrapper for TokenRequest -->             <xs:complexType name="getToken">               <xs:sequence>                 <xs:element minOccurs="1" name="tokenRequest" type="tns:tokenRequest" />               </xs:sequence>             </xs:complexType>              <!-- TokenResponse -->             <xs:complexType name="tokenResponse">                 <xs:sequence>                     <xs:element minOccurs="1" name="ideasArtifactReceiverURL" type="xs:string" />                     <xs:element minOccurs="1" name="ideasMAURL" type="xs:string" />                     <xs:element minOccurs="1" name="errorCode" type="xs:string" />                     <xs:element minOccurs="1" name="errorMessage" type="xs:string" />                 </xs:sequence>             </xs:complexType>              <!-- getTokenResponse, a wrapper for TokenResponse -->             <xs:complexType name="getTokenResponse">                 <xs:sequence>                     <xs:element minOccurs="1" name="return" type="tns:tokenResponse" />                 </xs:sequence>             </xs:complexType>              <xs:element name="getToken" type="tns:getToken" />             <xs:element name="batchCommand" type="tns:batchCommand" />             <xs:element name="httpHeaders" type="tns:httpHeaders" />             <xs:element name="getTokenResponse" type="tns:getTokenResponse" />          </xs:schema>     </types>      <message name="TokenService_getToken">         <part element="tns:getToken" name="getToken" />     </message>      <message name="TokenService_getToken2">         <part element="tns:getToken" name="getToken" />         <part element="tns:batchCommand" name="batchCommand" />         <part element="tns:httpHeaders" name="httpHeaders" />     </message>      <message name="TokenService_getTokenResponse">         <part element="tns:getTokenResponse" name="getTokenResponse" />     </message>      <portType name="TokenService">         <operation name="getToken" parameterOrder="getToken">             <input message="tns:TokenService_getToken" />             <output message="tns:TokenService_getTokenResponse" />         </operation>         <operation name="getToken2" parameterOrder="getToken batchCommand httpHeaders">             <input message="tns:TokenService_getToken2" />             <output message="tns:TokenService_getTokenResponse" />         </operation>     </portType>      <binding name="TokenServiceBinding" type="tns:TokenService">         <soap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http" />         <operation name="getToken">             <soap:operation soapAction="" />             <input>                 <soap:body use="literal" />             </input>             <output>                 <soap:body use="literal" />             </output>         </operation>         <operation name="getToken2">             <soap:operation soapAction="" />             <input>                 <soap:body use="literal" />             </input>             <output>                 <soap:body use="literal" />             </output>         </operation>     </binding>      <service name="TokenService">         <port binding="tns:TokenServiceBinding" name="TokenServicePort">             <soap:address location="https://www0.ideas.hksarg/ideas/TokenService" />         </port>     </service>  </definitions> 

When I generate a stub (using Eclipse Oxygen, top-down, Axis1), the function are generated like these:

public TokenNamespace.ideas.mace.TokenResponse getToken(TokenNamespace.ideas.mace.TokenRequest tokenRequest) throws java.rmi.RemoteException {     return null; }  public TokenNamespace.ideas.mace.TokenResponse getToken2(TokenNamespace.ideas.mace.TokenRequest tokenRequest, boolean stopOnAnyError, TokenNamespace.ideas.mace.EACommand[] command, TokenNamespace.ideas.mace.HttpHeader[] httpHeader) throws java.rmi.RemoteException {     return null; } 

Why is TokenRequest class kept intact, while BatchCommand and HttpHeaders are dismantled?

I tried adding more sub-elements under HttpHeaders and BatchCommand, but they just get split up as additional parameters. I can't spot any difference between their declarations and getToken's.

1 Answers

Answers 1

If you are talking about getToken2() method then actually they are not dismantled rather if you see httpheaders is actually an array of httpheader so in java code it is converted to an array of httpheaders as parameter to getToken2 and same is the case for the CommandBatch.

And

If you are talking about why they are dismantled from getToken() method then the solution is as given below.

This is because in the wsdl file you have not defined the parameters for getToken() method

For example you have this

<portType name="TokenService">         <operation name="getToken" parameterOrder="getToken">             <input message="tns:TokenService_getToken" />             <output message="tns:TokenService_getTokenResponse" />         </operation>         <operation name="getToken2" parameterOrder="getToken batchCommand httpHeaders">             <input message="tns:TokenService_getToken2" />             <output message="tns:TokenService_getTokenResponse" />         </operation>     </portType> 

You should update it like below

<portType name="TokenService">         <operation name="getToken" parameterOrder="getToken batchCommand httpHeaders">             <input message="tns:TokenService_getToken" />             <output message="tns:TokenService_getTokenResponse" />         </operation>         <operation name="getToken2" parameterOrder="getToken batchCommand httpHeaders">             <input message="tns:TokenService_getToken2" />             <output message="tns:TokenService_getTokenResponse" />         </operation>     </portType> 

That is your operation getToken should define the required parameters in the parameterOrder attribute.

And also change the message from

<message name="TokenService_getToken">         <part element="tns:httpHeaders" name="httpHeaders" />     </message> 

to

<message name="TokenService_getToken">         <part element="tns:getToken" name="getToken" />         <part element="tns:batchCommand" name="batchCommand" />         <part element="tns:httpHeaders" name="httpHeaders" />     </message> 

After that it generates the code correctly.

Read More

Sunday, November 19, 2017

Soap Client Complex Type PHP Request

Leave a Comment

I have a web-service with following link I'm trying to access the function name with SubmitRequestType but it seems the function is not exist instead submitAnsiSingle this is the correct function name what I tried so far is ,

$wsdl = 'https://ww3.navicure.com:7000/webservices/NavicureSubmissionService?WSDL';  class SecurityHeaderType {         private $submitterIdentifier;         private $originatingIdentifier;         private $submitterPassword;         private $submissionId;         function SecurityHeaderType() {             $this->submitterIdentifier = '***';             $this->originatingIdentifier = '****';             $this->submitterPassword = '****';             $this->submissionId = '';          }            }  class SubmitRequestType {          private $submitterIdentifier;         private $originatingIdentifier;         private $submitterPassword;         private $submissionId;         private $timeout;         private $transactionType;         private $submittedAnsiVersion;         private $resultAnsiVersion;         private $submitterSubmissionId;         private $processingOption;         private $payload;         private $exceptions;          function SubmitRequestType() {          $this->submitterIdentifier = '***';         $this->originatingIdentifier = '***';         $this->submitterPassword = '**';         $this->submissionId = '**';         $this->timeout = 60 ;         $this->transactionType = "E";         $this->submittedAnsiVersion = '5010';         $this->resultAnsiVersion = '5010';         $this->submitterSubmissionId = '**';         $this->processingOption = 'R';         $this->payload = 'EDI-270-Request';         $this->exceptions = true;         } }  $soapheader = new SecurityHeaderType();   $submitrequest = new SubmitRequestType();        $service = new \SoapClient($wsdl);     $result= $service->SubmitAnsiSingle($submitrequest);     echo "<pre/>";print_r($result);      $types = $service->__getTypes ();     $functions = $service->__getFunctions ();     //echo "<pre/>";print_r($types);     //echo "<pre/>";print_r($functions); 

But I'm getting the response like below it seems the request is processing on their end but the SecurityHeaderType is not parsing their end.

stdClass Object (     [transactionTyp] => E     [submitterSubmissionId] => ****     [submittedAnsiVersion] => 5010     [resultAnsiVersion] => 5010     [statusHeader] => stdClass Object         (             [statusCode] => 1150             [statusMessage] => com.navicure.webservices.core.WSCoreException: Account does not exist for ''             [requestProcessed] =>          )  ) 

Any hint will be highly appreciate

Thanks in advance.

2 Answers

Answers 1

I found the solution!. It seems the PHP -> .NET web service comparability issue. So from PHP the complex type SOAP (this kind of format) can't access I found some usefull post here. So I switched SOAP to plain XML request with CURL and it seems working fine!. Also from WSDL link we can extract the request template using this online service . So my final code look like below.

$xml_data = "<?xml version='1.0' encoding='UTF-8'?> <s12:Envelope xmlns:s12='http://www.w3.org/2003/05/soap-envelope'>   <s12:Header>     <ns1:SecurityHeaderElement xmlns:ns1='http://www.navicure.com/2009/11/NavicureSubmissionService'>       <ns1:originatingIdentifier>****</ns1:originatingIdentifier>       <ns1:submitterIdentifier>****</ns1:submitterIdentifier>       <ns1:submitterPassword>***</ns1:submitterPassword>       <ns1:submissionId>?999?</ns1:submissionId>     </ns1:SecurityHeaderElement>   </s12:Header>   <s12:Body>     <ns1:SubmitAnsiSingleRequestElement xmlns:ns1='http://www.navicure.com/2009/11/NavicureSubmissionService'>       <ns1:timeout>60</ns1:timeout>       <ns1:transactionType>E</ns1:transactionType>       <ns1:submittedAnsiVersion>5010</ns1:submittedAnsiVersion>       <ns1:resultAnsiVersion>5010</ns1:resultAnsiVersion>       <ns1:submitterSubmissionId></ns1:submitterSubmissionId>       <ns1:processingOption>R</ns1:processingOption>       <ns1:payload>EDI270Payload</ns1:payload>     </ns1:SubmitAnsiSingleRequestElement>   </s12:Body> </s12:Envelope>"; $URL = "https://ww3.navicure.com:7000/webservices/NavicureSubmissionService";  $ch = curl_init($URL); curl_setopt($ch, CURLOPT_HTTPHEADER, array('Content-Type: text/xml')); curl_setopt($ch, CURLOPT_POST, 1); curl_setopt($ch, CURLOPT_POSTFIELDS, "$xml_data"); curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); $output = curl_exec($ch); curl_close($ch);   print_r($output); 

Hope this will help someone else in future.

Answers 2

You might be running into PHP's slightly less than compatible WSDL2 implementation. You could try the following and cross your fingers;

Headerbody needs to be implemented in the same depth as defined in xml, since I do not have access to navicure's documentation here's example code:

$headerbody = array('Token' => $someToken,                      'Version' => $someVersion,                      'UserCredentials'=>array('UserID'=>$UserID,                                               'Password'=>$Pwd));   //Create Soap Header.         $header = new SOAPHeader($namespace, 'RequestorCredentials', $headerbody);   

// In case multiple headers are required, create $headers[] = $header, and append to headers after.

$options = array(         'uri'=>'http://schemas.xmlsoap.org/soap/envelope/',         'style'=>SOAP_RPC,         'use'=>SOAP_ENCODED,         'soap_version'=>SOAP_1_1,         'cache_wsdl'=>WSDL_CACHE_NONE,         'connection_timeout'=>15,         'trace'=>true,         'encoding'=>'UTF-8',         'exceptions'=>true,     ); try {     $soap = new SoapClient($wsdl, $options);     $soap->__setSoapHeaders($header);     $data = $soap->SubmitAnsiSingle(array($submitrequest)); } catch(Exception $e) {     die($e->getMessage()); } 

Hope this is of any use - in case WSDL2 is actually used you might be able to get it to work with nusoap which can be found on sourceforge. Although that hasn't been updated in quite a while..

Read More

Monday, November 6, 2017

Execute process from spring webservice and monitor?

Leave a Comment

Question : I want to execute java jar file from webservice in spring boot project. and want to monitor it.

Problem : I am able to execute this process but problem is that process did not processed further.

I want to know why this process is waiting and why its not processed. how can i monitor its progress.

its get processed on following conditions:

  1. Once i stop the spring boot project or tomcat.
  2. Its get processed if i remove process.waitFor();

I tried the solution from this, that is execute the process from another thread.

My web service call

@RequestMapping(value="/startAnalysis", method=RequestMethod.POST) public String startAnalysis() {     List<String> cmd = new ArrayList<>();     cmd.add("java");     cmd.add("-jar");     cmd.add("test.jar");     try {             //Process p = Runtime.getRuntime().exec(cmd.toArray(new String[0]));              //ProcMon procMon = new ProcMon(cmd);             //Thread t = new Thread(procMon);             //t.setName("procMon");             //t.start();              ProcessBuilder processBuilder = new ProcessBuilder(cmd);             Process process = processBuilder.start();             process.waitFor();      } catch (Exception e) {         e.printStackTrace();     }     return "success"; } 

Thanks in advanced.

2 Answers

Answers 1

Often the process waits for it's output to be consumed by the calling process. Sometimes this simply means the output gets displayed on the terminal but in this case you might need to read the inputstream until it blocks. If you don't know how the process is supposed to behave you might just want to read the process.getInputStream() in a separate thread. It's also possible your process is waiting for something to be written to the process.getOutputStream() in some states.

Either you need to check the documentation of the jar, or try it by executing it straight from a command prompt/shell and see how it behaves. Then you can change your application to read the output as you expect it to behave.

In lots of applications the output is most easily read line-by-line:

final String EXPECTED_OUTPUT = "Hello World";  BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream())); String firstLine = reader.readLine(); if (!firstLine.equals(EXPECTED_OUTPUT)) {     // handle unexpected situation } // maybe handle some more output // or send something to the process.getOutputStream() in response // and finally wait for the application to exit when it should be done process.waitFor(); 

Answers 2

Please find an elaborate reasoning of why a call to process.waitFor() would not return at all in some cases, here.

Alternatively, see if its possible for you to use the alternate version of waitFor() method where we provide the timeOut value.

Read More

Wednesday, October 25, 2017

Apache CXF Client for Microsoft WCF service with MTOM returning 400

Leave a Comment

I have an apache CXF client for a Microsoft WCF service, and I am attempting to send a file via MTOM. However, I keep getting a 400, and the error on the WCF side according to the partner is that there is an error creating the MTOM reader

I've traced the outbound message, and it looks like this:

INFO: Outbound Message --------------------------- ID: 1 Address: https://someserver.com/ImportService.svc?wsdl Encoding: UTF-8 Http-Method: POST Content-Type: multipart/related; type="application/xop+xml"; boundary="uuid:1d46d7c9-047b-440d-928b-ab8689ab5e6f"; start="<root.message@cxf.apache.org>"; start-info="application/soap+xml; action=\"http://tempuri.org/IImportService/UploadFile\"" Headers: {Accept=[*/*], Accept-Encoding=[gzip;q=1.0, identity; q=0.5, *;q=0], Content-Encoding=[gzip]} Payload: --uuid:1d46d7c9-047b-440d-928b-ab8689ab5e6f Content-Type: application/xop+xml; charset=UTF-8; type="application/soap+xml; action=\"http://tempuri.org/IImportService/UploadFile\"" Content-Transfer-Encoding: binary Content-ID: <root.message@cxf.apache.org>      <?xml version="1.0"?> <soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope">     <soap:Header>         <wsse:Security xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" soap:mustUnderstand="true">             <wsse:UsernameToken wsu:Id="UsernameToken-e51a6fdd-5053-4aae-a9fb-363dde7d9e77">                 <wsse:Username>blah@test.com</wsse:Username>                 <wsse:Password Type="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText">mypassword</wsse:Password>             </wsse:UsernameToken>         </wsse:Security>         <ns2:letterOptions xmlns="http://schemas.datacontract.org/2004/07/PublicServices.Import" xmlns:ns2="http://tempuri.org/">             <EnableQBPlanConsolidation>false</EnableQBPlanConsolidation>             <MASKSSN>true</MASKSSN>             <SRPrintedNumberofDays>2</SRPrintedNumberofDays>             <SuppressAllLetters>false</SuppressAllLetters>             <SuppressNewMemberLoginLetter>false</SuppressNewMemberLoginLetter>             <SuppressTakeOverLetterForTermed>false</SuppressTakeOverLetterForTermed>             <SuppressTerminationLetter>false</SuppressTerminationLetter>         </ns2:letterOptions>         <ns2:JobQueueType xmlns="http://schemas.datacontract.org/2004/07/PublicServices.Import" xmlns:ns2="http://tempuri.org/">Import</ns2:JobQueueType>         <Filename xmlns="http://tempuri.org/">testImport.csv</Filename>         <Action xmlns="http://www.w3.org/2005/08/addressing">http://tempuri.org/IImportService/UploadFile</Action>         <MessageID xmlns="http://www.w3.org/2005/08/addressing">urn:uuid:f380e4cc-225f-4b7d-bd46-6b5d607a59ca</MessageID>         <To xmlns="http://www.w3.org/2005/08/addressing">https://someserver.com/ImportService.svc?wsdl</To>         <ReplyTo xmlns="http://www.w3.org/2005/08/addressing">             <Address>http://www.w3.org/2005/08/addressing/anonymous</Address>         </ReplyTo>     </soap:Header>     <soap:Body>         <FileUploadMessage xmlns="http://tempuri.org/" xmlns:ns2="http://schemas.datacontract.org/2004/07/PublicServices.Import" xmlns:ns3="http://schemas.microsoft.com/2003/10/Serialization/">             <FileByteStream>                 <xop:Include xmlns:xop="http://www.w3.org/2004/08/xop/include" href="cid:68e0408d-81da-496b-a06c-24a0459207d1-1@tempuri.org"/>             </FileByteStream>         </FileUploadMessage>     </soap:Body> </soap:Envelope> --uuid:1d46d7c9-047b-440d-928b-ab8689ab5e6f Content-Type: application/octet-stream Content-Transfer-Encoding: binary Content-ID: <68e0408d-81da-496b-a06c-24a0459207d1-1@tempuri.org>  [VERSION],1.0 [NPM],552652222,1,Basic Client,Basic Client,Bob,Z,Jones,MR,bjones@test.com,402444555,,1234 Some street,,Omaha,NE,68123,,M,T,F,F  --uuid:1d46d7c9-047b-440d-928b-ab8689ab5e6f-- 

I've found plenty of other instances where other folks had the same issue: https://coderanch.com/t/224995/java/Apache-CXF-MTOM-enabled-WCF

HTTP Bad Request error when requesting a WCF service contract

http://mail-archives.apache.org/mod_mbox/cxf-users/201211.mbox/%3CCAPXLCrCLkSkC8dQFeuU8DLY6gne1SOhwT9eMDxAUxLudnqU+YA@mail.gmail.com%3E

None of these were able to resolve my issue. I've tried multiple different versions of CXF and I get the same error with all of them.

This is a consolidated version of the code that is calling the service:

    JaxWsProxyFactoryBean proxyFactory = new JaxWsProxyFactoryBean();     proxyFactory.setBindingId(SOAPBinding.SOAP12HTTP_MTOM_BINDING);     proxyFactory.setServiceClass(IImportService.class);     proxyFactory.setAddress(proxyEndpoint);     proxyFactory.getFeatures().add(new WSAddressingFeature());      IImportService importService = (IImportService) proxyFactory.create();      Client client = (Client) importService;      LetterOptions letterOptions = new LetterOptions();     letterOptions.setSRPrintedNumberofDays(2);     letterOptions.setMASKSSN(true);     letterOptions.setEnableQBPlanConsolidation(false);      List<Object> headerList = new ArrayList<>();      headerList.add(new Header(new QName("http://tempuri.org/", "letterOptions"),             letterOptions, new JAXBDataBinding(LetterOptions.class)));     headerList.add(new Header(new QName("http://tempuri.org/", "JobQueueType"), JobQueueType.IMPORT, new JAXBDataBinding(JobQueueType.class)));     headerList.add(new Header(new QName("http://tempuri.org/", "Filename"), "testImport.csv", new JAXBDataBinding(String.class)));      client.getRequestContext().put(Header.HEADER_LIST, headerList);     client.getEndpoint().getActiveFeatures().add(new LoggingFeature());      client.getInInterceptors().add(new GZIPInInterceptor());     client.getInInterceptors().add(new LogResponseInterceptor());      GZIPOutInterceptor outInterceptor = new GZIPOutInterceptor();     outInterceptor.setForce(true);     client.getOutInterceptors().add(outInterceptor);      Map props = new HashMap();     props.put(WSHandlerConstants.ACTION, WSHandlerConstants.USERNAME_TOKEN);     props.put(WSHandlerConstants.PASSWORD_TYPE, WSConstants.PW_TEXT);     props.put(WSHandlerConstants.PW_CALLBACK_CLASS, PasswordCallbackHandler.class.getName());     props.put(WSHandlerConstants.USER, "blah@test.com");     WSS4JOutInterceptor wssOut = new WSS4JOutInterceptor(props);     client.getOutInterceptors().add(wssOut);      HTTPConduit conduit = (HTTPConduit) client.getConduit();     HTTPClientPolicy policy = conduit.getClient();     if(policy == null) {         policy = new HTTPClientPolicy();     }     policy.setAllowChunking(false);      FileUploadMessageReponse response = importService.uploadFile(fileUploadMessage); 

One interesting tidbit is that I can copy the same request that is being logged into SoapUI, and it works fine.

0 Answers

Read More

Saturday, October 21, 2017

Weird error when invoking soap - llegalAccessError: tried to access field org.apache.cxf.staxutils.OverlayW3CDOMStreamWriter.isOverlaid

Leave a Comment

Ive been working on a soap client since a time and I still cannot figure it out.

I have this error:

Exception in thread "main" java.lang.IllegalAccessError: tried to access field org.apache.cxf.staxutils.OverlayW3CDOMStreamWriter.isOverlaid from class org.apache.cxf.binding.soap.saaj.SAAJStreamWriter         at org.apache.cxf.binding.soap.saaj.SAAJStreamWriter.getPrefix(SAAJStreamWriter.java:79)         at org.apache.cxf.binding.soap.interceptor.SoapOutInterceptor.writeSoapEnvelopeStart(SoapOutInterceptor.java:109)         at org.apache.cxf.binding.soap.interceptor.SoapOutInterceptor.handleMessage(SoapOutInterceptor.java:87)         at org.apache.cxf.binding.soap.interceptor.SoapOutInterceptor.handleMessage(SoapOutInterceptor.java:67)         at org.apache.cxf.phase.PhaseInterceptorChain.doIntercept(PhaseInterceptorChain.java:308)         at org.apache.cxf.endpoint.ClientImpl.doInvoke(ClientImpl.java:514)         at org.apache.cxf.endpoint.ClientImpl.invoke(ClientImpl.java:423)         at org.apache.cxf.endpoint.ClientImpl.invoke(ClientImpl.java:324)         at org.apache.cxf.endpoint.ClientImpl.invoke(ClientImpl.java:277)         at org.apache.cxf.endpoint.ClientImpl.invokeWrapped(ClientImpl.java:312)         at org.apache.cxf.jaxws.DispatchImpl.invoke(DispatchImpl.java:321)         at org.apache.cxf.jaxws.DispatchImpl.invoke(DispatchImpl.java:240)         at com.sigetel.web.web.rest.consumer.SoapClient.invoke(SoapClient.java:63)         at com.sigetel.web.web.rest.consumer.SoapClient.main(SoapClient.java:37)     Disconnected from the target VM, address: '127.0.0.1:60128', transport: 'socket'  Process finished with exit code 1 

I saw its kinda common but still cannot make it work.

Here is my code:

 Dispatch<SOAPMessage> dispatch = service.createDispatch(portName, SOAPMessage.class, Service.Mode.MESSAGE);         SOAPMessage response;         SOAPBody responseBody;         dispatch.getRequestContext().put(Dispatch.SOAPACTION_USE_PROPERTY, true);         dispatch.getRequestContext().put(Dispatch.SOAPACTION_URI_PROPERTY, soapActionUri);         try {             MessageFactory messageFactory = MessageFactory.newInstance();             SOAPMessage message = messageFactory.createMessage();             SOAPPart soapPart = message.getSOAPPart();             StreamSource msgSrc = new StreamSource(new StringReader(request));             soapPart.setContent(msgSrc);             message.saveChanges();               response = dispatch.invoke(message);             responseBody = response.getSOAPBody(); .... 

Reelevant dependencies that might be related:

<dependency>             <groupId>org.apache.cxf</groupId>             <artifactId>cxf-rt-transports-http-jetty</artifactId>             <version>3.1.6</version>         </dependency>          <dependency>             <groupId>com.sun.jersey</groupId>             <artifactId>jersey-client</artifactId>             <version>1.8</version>         </dependency>          <dependency>             <groupId>com.sun.jersey</groupId>             <artifactId>jersey-core</artifactId>             <version>1.9</version>         </dependency>          <dependency>             <groupId>javax.xml.ws</groupId>             <artifactId>jaxws-api</artifactId>             <version>2.2.11</version>         </dependency>          <dependency>             <groupId>org.apache.ws.security</groupId>             <artifactId>wss4j</artifactId>             <version>1.6.11</version>         </dependency> 

EDITED:

and these ones:

<dependency>     <groupId>org.apache.cxf</groupId>     <artifactId>cxf-spring-boot-starter-jaxws</artifactId>     <version>3.1.11</version> </dependency> 

Any idea about this error?

2 Answers

Answers 1

As you may have already noticed, you have incompatible versions of SAAJStreamWriter and OverlayW3CDOMStreamWriter.

SAAJStreamWriter is located in package cxf-rt-bindings-soap, which is provided by:

<dependency>     <groupId>org.apache.cxf</groupId>     <artifactId>cxf-spring-boot-starter-jaxws</artifactId>     <version>3.1.11</version> </dependency> 

OverlayW3CDOMStreamWriter is located in pachage cxf-core, which is provided by:

<dependency>     <groupId>org.apache.cxf</groupId>     <artifactId>cxf-rt-transports-http-jetty</artifactId>     <version>3.1.6</version> </dependency> 

Try one of the latest versions of org.apache.cxf - 3.1.13 or 3.2.0 - the same version for both dependencies.

Answers 2

You are pulling incorrect version of OverlayW3CDOMStreamWriter.

SAAJStreamWriter extends OverlayW3CDOMStreamWriter which has isOverlaid field.

The isOverlaid was changed from package private to protected in 3.2 version and was backported to 3.1.7 version so it can accessed in sub class SAAJStreamWriter

Both the below dependencies is pulling cxf core which has OverlayW3CDOMStreamWriter

1.

<dependency>     <groupId>org.apache.cxf</groupId>     <artifactId>cxf-spring-boot-starter-jaxws</artifactId>     <version>3.1.11</version> </dependency> 

cxf-rt-frontend-jaxws - cxf-rt-bindings-soap - 3.1.11 for SAAJStreamWriter

cxf-rt-transports-http - cxf-core - 3.1.11 for OverlayW3CDOMStreamWriter

2.

<dependency>     <groupId>org.apache.cxf</groupId>     <artifactId>cxf-rt-transports-http-jetty</artifactId>     <version>3.1.6</version> </dependency> 

cxf-rt-transports-http - cxf-core - 3.1.6 for OverlayW3CDOMStreamWriter

cxf core 3.1.6 was chosen over 3.1.11 since it is nearer as by default maven resolves version conflicts with a nearest-wins strategy.

So in essence 3.1.11 SAAJStreamWriter class was expecting 3.1.11 OverlayW3CDOMStreamWriter but found 3.1.6 OverlayW3CDOMStreamWriter where the isOverlaid was package private and is the reason for your error.

Fix change to use 3.1.11 for jetty dependency or atleast use version 3.1.7 for both above dependencies.

<dependency>     <groupId>org.apache.cxf</groupId>     <artifactId>cxf-rt-transports-http-jetty</artifactId>     <version>3.1.11</version> </dependency> 

This will pull the 3.1.11 for both cxf core and cxf bindings and should resolve the error.

Read More

Thursday, October 19, 2017

Load Balancer sticky sessions and very old webservices

Leave a Comment

With a hardware LoadBalancer, you can configure sticky sessions which will make sure the same session will always go to the same server.

But will this work with webservices also (rather than webservers)?

i.e. I have WebServices hosted behind a Load Balancer.

Will Webservice calls coming from different native clients (not browser clients) always go to the same webservice server?

These are very old style Webservices - uses RPC/Encoding - the native client program uses Axis 1.4 for the client stubs.

3 Answers

Answers 1

Webservice calls coming from different native clients (not browser clients) always go to the same webservice server should be possible.

To maintain the session stickiness, mostly load balance inject the server identifier in cookie while responding back to the client(kindly note cookie is not a browser feature it is HTTP feature defined by this specification) and should be supported by the HTTP client which is used by Axis 1.4 underneath).

I suggest you to to analyze how your load balance works and based on that you may have to change your needs to change your clients. If your load-balance uses the cookie based approach, this answer you may found useful.

Hope this helps.

Answers 2

If you can keep your application stateless,make it it's good in both performance and scalability.

Benefits of stateless :

  • Scalability. You can have as many servers as we want without having to share a user session. Each of them can process request (e.g. load balancing via round robin).

  • Saves server resources. We do not need to allocate memory on the server side (again - scalability).

  • No need to recover after a server restart.

Session stickiness can be tricky to get right. For example, if your web servers are running on multi-core machines, and you have several processes handling web traffic, you'll need a way to be sticky to both a specific machine and a single process on that machine. So make sure your system degrades well in cases where stickiness doesn't work correctly.

Good discussion you can find here : Sticky and NON-Sticky sessions

Sticky session pro and cons : Pros and Cons of Sticky Session / Session Affinity load blancing strategy?

Now come to your question :

Will Webservice calls coming from different native clients (not browser clients) always go to the same webservice server?

Yes in sticky session .

These are very old style Webservices - uses RPC/Encoding - the native client program uses Axis 1.4 for the client stubs.

Session configuration you need load balancer/server and it can handle any old or new type of applications

this work with webservices also (rather than webservers)?

No its configuration you need to make on server level.

Answers 3

It will work as long as your native client correctly manage the session, ie. set the correct http header for each request.

Generally sticky session is managed by the load balancer by modifying the session cookie to add the server identity.

HA-proxy example

There must be a dedicated documentation for your load balancer.

Read More

Thursday, October 5, 2017

PHP SOAP Clients http headers Error

Leave a Comment

I need to consume a web service https://www.example.com/example.svc?wsdl in PHP. For this purpose, I am using PHP SOAP client. The code snippet like below:

$client = new SoapClient("https://www.example.com/example.svc?wsdl",     array('soap_version' => SOAP_1_2,         'location'=>'https://www.example.com/example.svc',         'login'=> '#####',         'password'=> '#######',         'exceptions'=>true,         'trace'=>1,         'cache_wsdl'=>WSDL_CACHE_NONE,         'encoding'=>'UTF-8',         'connection_timeout' => 500,         'keep_alive' =>false));  $client->__call('getProductList',array()); 

However, when I run this its through following error:

Warning: SoapClient::__doRequest(): SSL: The operation completed successfully. in E:\location\test1.php on line 37  Fatal error: Uncaught SoapFault exception: [HTTP] Error Fetching http headers in E:\location\test1:37 Stack trace: #0 [internal function]: SoapClient->__doRequest('<?xml version="...', 'https://travius...', 'Travius/ITraviu...', 2, 0) #1 E:\location\test1(37): SoapClient->__call('getProductList', Array) #2 {main} thrown in E:\location\test1.php on line 37 

I am struggling several days to solve the error but can't figure out. I tried the different solution in stack overflow like 'keep_alive' =>false, connection_timeout but nothing works.

I also try with php nusoap library. its request and response are like following:

Error  HTTP Error: Unsupported HTTP response status 400 Bad Request (soapclient->response has contents of the response)  Request  POST /#####.svc?wsdl HTTP/1.0 Host: #####.#####.eu User-Agent: NuSOAP/0.9.5 (1.123) Content-Type: application/soap+xml;charset=UTF-8; charset=UTF-8 SOAPAction: "" Authorization: Basic RGVtb2FwaTpEdXE1dmRWdA== Content-Length: 529  <?xml version="1.0" encoding="UTF-8"?><SOAP-ENV:Envelope SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" xmlns:SOAP-ENV="http://www.w3.org/2003/05/soap-envelope" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/"><SOAP-ENV:Body><GetProduct><parameters><intProductID xsi:type="xsd:int">1266</intProductID><lang xsi:type="xsd:string">CN</lang></parameters></GetProduct></SOAP-ENV:Body></SOAP-ENV:Envelope>  Response  HTTP/1.1 400 Bad Request Server: Microsoft-IIS/7.5 X-Powered-By: ASP.NET Date: Mon, 02 Oct 2017 16:03:04 GMT Content-Length: 0 

Please note that this web service works fine in .Net application. Any help highly appreciated. Thanks in advance.

2 Answers

Answers 1

Judging from the error that you posted in your question please change the following line.

$client->__call('getProductList',array()); 

with this

try {     $soapResponse = $client->__soapCall('getProductList',array());     var_dump($soapResponse); }  catch (SoapFault $e) {      exit("Error using method \"getProductList\" having errorCode \"".$e->faultcode."\""); } 

I don't know what php version you use (you have not posted relevant information) but i think in your case _call is deprecated.

Calling this method directly is deprecated. Usually, SOAP functions can be called as methods of the SoapClient object; in situations where this is not possible or additional options are needed, use SoapClient::__soapCall().

Answers 2

Hi Did you try to write your soap header as wssecurity you can see samples

or this in stackoverflow

Read More

Tuesday, September 26, 2017

Java WSDL modify or hide certain properties on Web View

Leave a Comment

TLDR Is it possible to create an "alias" for the IP address (such as 0.0.0.0:8080/services as SERVER_1) or any other property on the WSDL content while someone's reading it? Similar to:

<entry key="org.apache.cxf.endpoint.private" value="true"/> 

For the services list, that keeps the functionality intact but hides the services list.

If yes, how? If not, is there a way to hide it without using @XmlTransient because if we used it, and from my understanding, the program wouldn't even map this element and thus no longer work.


I'm working with SOAP services using Spring and JAX-RS.

We're securing our apps, after an ethical hacking test, the results thrown that we were exposing services and production IP addresses on our URLs.

We were able to hide the services list from the web view, for example, if we access http://localhost:8080/foo/services we get this text:

No services have been found. 

Which is fine and we've done it by following this answer, but instead of being on cxf-servlet.xml file, it was on the applicationContext-{moduleName}.xml file.

Now, if we know, or have access to any of the WSDL paths, we can still see the WSDL contents (which includes production IP addresses), for example if we entered:

http://localhost:8080/foo/services/bar?_wsdl 

We have a similar definition as below (I edited it for security reasons):

<application     xmlns="http://wsdl.dev.java.net/2009/02"     xmlns:xs="http://www.w3.org/2001/XMLSchema">     <grammars/>     <resources base="http://localhost:8080/foo/services/bar">         <resource path="/VX">             <resource path="/anotherPath">                 <method name="POST">                     <request>                         <representation mediaType="application/x-www-form-urlencoded">                             <param name="someParam" style="query" type="xs:string"/>                         </representation>                     </request>                     <response>                         <representation mediaType="application/json">                             <param name="anotherParam" style="plain" type="xs:string"/>                         </representation>                     </response>                 </method>             </resource>         </resource>     </resources> </application> 

How could I, for example edit on run time the property

<resources base="http://localhost:8080/foo/services/bar"> 

To something like

<resources base="SERVER_1"> 

So, we internally know what IP address does SERVER_1 has, but people outside that manage to get there doesn't, in other words how could I create an alias for the IP address and use it instead of the real ip address on it?

This is because we have about 10 servers, each with a different IP address, and if we need to do some production debugging we need to know which server we're in, so we would like to avoid hiding the whole WSDL content (as I know it can be done, because a module has this configuration).

I know I can use @XmlTransient annotation, but as per docs:

Prevents the mapping of a JavaBean property/type to XML representation.

So, in my understanding, if I use this annotation over the property containing the IP address, then it would no longer be working.

If this isn't possible, which other suggestions would you have in order to make a workaround for this particular case?

We create the services with top-down approach (i.e. we're given the WSDL and we use wsdl2java to create Java Objects + service interface from it)

1 Answers

Answers 1

TLDR: Use DNS to assign names to your IP addresses.

We're securing our apps, after an ethical hacking test, the results thrown that we were exposing services and production IP addresses on our URLs

You have a SOAP-Service. To use it one needs to know the address of the endpoint. So you'll "expose" it no matter what. Security through obscurity is not recommended.

So, we internally know what IP address does SERVER_1 has, but people outside that manage to get there doesn't, in other words how could I create an alias for the IP address and use it instead of the real ip address on it?

That's what DNS was invented for. An "alias" for the IP address. It's bad practise to use IP-Addresses for services. So set up a DNS (or use host files) to assign a name per IP address.

Read More

Wednesday, September 20, 2017

what is the correct way to create a REST endpoint with relationship

Leave a Comment

I want to create some endpoints to retrieve exceptions per country, startTime and endTime but i don't know what is the correct way to structure the endpoints, i have been talking with my co workers and we have different opinions about how to do it :

Option 1 Path params

  • /countries/{countryCode}/exceptions?startTime={value}&endTime={value} : To get all the exceptions per country in a certain timeframe

  • /countries/*/exceptions?startTime={value}&endTime={value} :To get all the exceptions in a certain timeframe

Option 2 Query params

  • /exceptions?country={countryCode}&startTime={value}&endTime={value} :To get all the exceptions per country in a certain timeframe

  • /exceptions?startTime={value}&endTime={value} :To get all the exceptions in a certain timeframe

Option 3 Path params in a different order

  • /exceptions/countries/{countryCode}?startTime={value}&endTime={value} :To get all the exceptions per country in a certain timeframe

  • /exceptions?startTime={value}&endTime={value}: To get all the exceptions in a certain timeframe

All the 3 options have pros and cons but we don't agree in which is the best practice. The question is what is the best option to create these endpoints.

3 Answers

Answers 1

If the exception needs a country to exist, that is, the exception is a sub resource of country, consider:

/countries/{countryCode}/exceptions?startTime={value}&endTime={value} 

Otherwise go for:

/exceptions?country={countryCode}&startTime={value}&endTime={value} 

Answers 2

Option 2 where Exception is a separate first-level entity and the endpoint accepts an optional country code as a filtering property makes the most sense based on the limited description of your requirements.

Answers 3

Path parameters should be used when you are displaying a hierarchy, e.g. to show all the comments that respond to the blog with id {id}, you would form this endpoint:

/blogs/{id}/comments 

If you would want to filter these comments base on time, you would use query parameters for that:

/blogs/{id}/comments?start={start}&end={end} 

In your case however, it seems, based on your question, that you have a large list with exceptions. This list can be filtered based on various aspects:

  • Country
  • Time

Since these properties are not part of the structural hierarchy (based on the context of your question), but simply properties giving more information about the exceptions, it would make sense to catch all them as query parameters to filter on, as such:

/exceptions?country={countryCode}&startTime={value}&endTime={value} 
Read More

Sunday, August 20, 2017

handleMessage method of SOAPHandler not getting invoked,rather getHeaders get invoked

Leave a Comment

I am new to the SOAP world.

I have coverted the wsdl file to java class using maven plugin

Below is the pom.xml configuration.

<plugin>             <groupId>org.apache.cxf</groupId>             <artifactId>cxf-codegen-plugin</artifactId>             <version>3.1.12</version>             <executions>                 <execution>                     <id>generate-sources</id>                     <phase>generate-sources</phase>                     <configuration>                         <sourceRoot>${project.basedir}/src/main/java</sourceRoot>                         <wsdlOptions>                             <wsdlOption>                                 <wsdl>${project.basedir}/src/main/resources/EIAproxy.wsdl</wsdl>                                 <wsdlLocation>classpath:EIAproxy.wsdl</wsdlLocation>                             </wsdlOption>                         </wsdlOptions>                     </configuration>                     <goals>                         <goal>wsdl2java</goal>                     </goals>                 </execution>             </executions>         </plugin> 

below is the class files

Interface definition

@WebService(targetNamespace = "http://schema.concierge.com", name = "EaiEnvelopeSoap") @XmlSeeAlso({com.concierge.schema.envelope.ObjectFactory.class, ObjectFactory.class}) @SOAPBinding(parameterStyle = SOAPBinding.ParameterStyle.BARE) public interface EaiEnvelopeSoap {  @WebResult(name = "clientRequestResponse", targetNamespace = "http://schema.concierge.com", partName = "parameters") @WebMethod(action = "http://www.openuri.org/clientRequest")   public ClientRequestResponse clientRequest(     @WebParam(partName = "parameters", name = "clientRequest", targetNamespace = "http://schema.concierge.com")     ClientRequest parameters ); } 

Here is class file that extends service

    @WebServiceClient(name = "EaiEnvelope",                       wsdlLocation = "classpath:EIAproxy.wsdl",                      targetNamespace = "http://schema.concierge.com")      public class EaiEnvelope extends Service {         public final static URL WSDL_LOCATION;         public final static QName SERVICE = new QName("http://schema.concierge.com", "EaiEnvelope");        public final static QName EaiEnvelopeSoap = new QName("http://schema.concierge.com", "EaiEnvelopeSoap");        static {            URL url = EaiEnvelope.class.getClassLoader().getResource("EIAproxy.wsdl");            if (url == null) {                java.util.logging.Logger.getLogger(EaiEnvelope.class.getName())                    .log(java.util.logging.Level.INFO,                          "Can not initialize the default wsdl from {0}", "classpath:EIAproxy.wsdl");            }                   WSDL_LOCATION = url;           }         public EaiEnvelope(URL wsdlLocation) {            super(wsdlLocation, SERVICE);        }         public EaiEnvelope(URL wsdlLocation, QName serviceName) {            super(wsdlLocation, serviceName);        }         public EaiEnvelope() {            super(WSDL_LOCATION, SERVICE);        }         public EaiEnvelope(WebServiceFeature ... features) {            super(WSDL_LOCATION, SERVICE, features);        }         public EaiEnvelope(URL wsdlLocation, WebServiceFeature ... features) {            super(wsdlLocation, SERVICE, features);        }         public EaiEnvelope(URL wsdlLocation, QName serviceName, WebServiceFeature ... features) {            super(wsdlLocation, serviceName, features);        }                /**         *         * @return         *     returns EaiEnvelopeSoap         */        @WebEndpoint(name = "EaiEnvelopeSoap")        public EaiEnvelopeSoap getEaiEnvelopeSoap() {            return super.getPort(EaiEnvelopeSoap, EaiEnvelopeSoap.class);        }         /**         *          * @param features         *     A list of {@link javax.xml.ws.WebServiceFeature} to configure on the proxy.  Supported features not in the <code>features</code> parameter will have their default values.         * @return         *     returns EaiEnvelopeSoap         */        @WebEndpoint(name = "EaiEnvelopeSoap")        public EaiEnvelopeSoap getEaiEnvelopeSoap(WebServiceFeature... features) {            return super.getPort(EaiEnvelopeSoap, EaiEnvelopeSoap.class, features);        }      }        

My SoapHandler file is

       import java.io.ByteArrayOutputStream;        import java.io.IOException;        import java.io.OutputStream;        import java.io.StringWriter;        import java.util.Set;         import javax.xml.namespace.QName;        import javax.xml.soap.SOAPBody;        import javax.xml.soap.SOAPElement;        import javax.xml.soap.SOAPEnvelope;        import javax.xml.soap.SOAPHeader;        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 com.xxx.fdp.common.LoggerManager;        import com.xxx.fdp.constants.LoggerConstantEnum;        import com.xxx.fdp.property.config.AbilityConfig;         public class HeaderHandler implements SOAPHandler<SOAPMessageContext> {             /** The logger manager. */            LoggerManager loggerManager = new LoggerManager();             @Override            public boolean handleMessage(SOAPMessageContext smc) {                 Boolean outboundProperty = (Boolean) smc.get(MessageContext.MESSAGE_OUTBOUND_PROPERTY);                loggerManager.info(LoggerConstantEnum.AbilityDailySyncUp, "Entered in handleMessage with outBoundProperty : " + outboundProperty);                if (outboundProperty.booleanValue()) {                     SOAPMessage message = smc.getMessage();                    loggerManager.info(LoggerConstantEnum.AbilityDailySyncUp, " Message : " + message);                     try {                        message.writeTo(System.out);                        SOAPEnvelope envelope = smc.getMessage().getSOAPPart().getEnvelope();                        envelope.addNamespaceDeclaration("com", "http://schema.concierge.com");                        message.getMimeHeaders().setHeader("Content-Type", "application/soap+xml; charset=utf-8");                        SOAPHeader header = envelope.addHeader();                         SOAPElement authentication = header.addChildElement("authentication", "auth", "http://schemas.eia.org/middleware/AuthInfo");                         SOAPElement username = authentication.addChildElement("user", "auth");                        username.addTextNode(AbilityConfig.getInstance().getSoapUser());                         SOAPElement password = authentication.addChildElement("password", "auth");                        password.addTextNode(AbilityConfig.getInstance().getSoapPassword());                         SOAPElement authType = authentication.addChildElement("type", "auth");                        authType.addTextNode(AbilityConfig.getInstance().getSoapAuthType());                        SOAPBody body = envelope.getBody();                         // Print out the outbound SOAP message to System.out                        message.saveChanges();                         loggerManager.info(LoggerConstantEnum.AbilityDailySyncUp, "Request Format : " + envelope.getBody() + ",Header : " + envelope.getHeader());                        ByteArrayOutputStream out = new ByteArrayOutputStream();                        message.writeTo(out);                        String strMsg = new String(out.toByteArray());                        loggerManager.info(LoggerConstantEnum.AbilityDailySyncUp, "Request Format Message: " + strMsg);                        StringWriter writer = new StringWriter();                        message.writeTo(new StringOutputStream(writer));                        // message.writeTo(System.out);                        System.out.println("");                     } catch (Exception e) {                        e.printStackTrace();                    }                 } else {                    try {                         // This handler does nothing with the response from the Web                        // Service so                        // we just print out the SOAP message.                        SOAPMessage message = smc.getMessage();                        loggerManager.info(LoggerConstantEnum.AbilityDailySyncUp, "Response Message : " + message);                        message.writeTo(System.out);                        System.out.println("");                     } catch (Exception ex) {                        ex.printStackTrace();                    }                }                loggerManager.info(LoggerConstantEnum.AbilityDailySyncUp, "Exit in handleMessage with outBoundProperty : " + outboundProperty);                return outboundProperty;             }             private static class StringOutputStream extends OutputStream {                 private StringWriter writer;                 public StringOutputStream(StringWriter writer) {                    this.writer = writer;                }                 @Override                public void write(int b) throws IOException {                    writer.write(b);                }            }             @Override            public boolean handleFault(SOAPMessageContext context) {                loggerManager.info(LoggerConstantEnum.AbilityDailySyncUp, "Entered in handleFault ");                return false;            }             @Override            public void close(MessageContext context) {                loggerManager.info(LoggerConstantEnum.AbilityDailySyncUp, "Entered in close ");            }             @Override            public Set<QName> getHeaders() {                // TODO Auto-generated method stub                return null;            }         } 

My handlerResolver file is

     import java.util.ArrayList;      import java.util.List;       import javax.xml.ws.handler.Handler;      import javax.xml.ws.handler.HandlerResolver;      import javax.xml.ws.handler.PortInfo;       import com.xxx.fdp.common.LoggerManager;      import com.xxx.fdp.constants.LoggerConstantEnum;        public class HeaderHandlerResolver implements HandlerResolver {           LoggerManager loggerManager = new LoggerManager();           @SuppressWarnings("rawtypes")          @Override          public List<Handler> getHandlerChain(PortInfo portInfo) {              loggerManager.info(LoggerConstantEnum.AbilityDailySyncUp,"Entered in getHandlerChain");              List<Handler> handlerChain = new ArrayList<Handler>();              loggerManager.info(LoggerConstantEnum.AbilityDailySyncUp,"Created handlerChanin object");              HeaderHandler headerHandler = new HeaderHandler();              loggerManager.info(LoggerConstantEnum.AbilityDailySyncUp,"Created HeaderHandler object");               handlerChain.add(headerHandler);              loggerManager.info(LoggerConstantEnum.AbilityDailySyncUp,"returned handlerChain");               return handlerChain;          }       } 

Method which is used to call service

        public void processRequest(EaiEnvelope envelope,AbilitySyncUpData abilityObject) {          loggerManager.info(LoggerConstantEnum.AbilityDailySyncUp, "| processing ability async up starts with TranactionId : "+abilityObject.getTransactionId());          try {              com.concierge.schema.EaiEnvelope service=new com.concierge.schema.EaiEnvelope();              HeaderHandlerResolver handlerResolver = new HeaderHandlerResolver();              service.setHandlerResolver(handlerResolver);              EaiEnvelopeSoap port=service.getEaiEnvelopeSoap();              ClientRequest request=new ClientRequest();              request.setEaiEnvelope(envelope);              loggerManager.info(LoggerConstantEnum.AbilityDailySyncUp,"Sending request to web service with TranactionId : "+abilityObject.getTransactionId());              ClientRequestResponse response=port.clientRequest(request);              loggerManager.info(LoggerConstantEnum.AbilityDailySyncUp,"Response received "+response+" After sending request to web service with TranactionId : "+abilityObject.getTransactionId());          } catch (Exception e) {              loggerManager.error(LoggerConstantEnum.AbilityDailySyncUp, "|  Exception occured  :  " + e.fillInStackTrace(), e);              writeCsvFile(abilityObject);          }          loggerManager.info(LoggerConstantEnum.AbilityDailySyncUp, "| processRequest method ends here with TranactionId : "+abilityObject.getTransactionId()); 

I am not able to get call in soapHandler's handleMessage method and call is going on getHeadersmethod when the service methodClientRequestResponse response=port.clientRequest(request);` is called.

I have reffered from several answers that are present on stackoverflow:

SoapHandler not called after WS operation is executed

https://stackoverflow.com/a/12712728/1569443

https://stackoverflow.com/a/14523921/1569443

http://www.javadb.com/using-a-message-handler-to-alter-the-soap-header-in-a-web-service-client/

https://soa2world.blogspot.com/2009/05/direct-web-service-client-using-java.html

I am still not able to call handleMessage method of handler as no logs gets printed. Call is made in handlerResolver class but not in HeaderHandler class.

How can I resolve this issue?

0 Answers

Read More