How to enable pretty logging of SOAP messages in JBoss 7 - web-services

I have enabled SOAP logging by adding following in standalone.xml as described in Jboss Advanced User Guide:
<system-properties>
<property name="org.apache.cxf.logging.enabled" value="true"/>
</system-properties>
This configuration does not pretty print XML messages. I am sure that CXF supports pretty printing since there is a AbstractLoggingInterceptor.setPrettyLogging() method in the library.
How can I enable pretty printing of SOAP requests and responses in JBoss 7.

Using org.apache.cxf.logging.enabled property is the right way, it accepts value "pretty" for nicely formatted xml output
<system-properties>
<property name="org.apache.cxf.logging.enabled" value="pretty"/>
</system-properties>
For details see https://github.com/apache/cxf/blob/master/core/src/main/java/org/apache/cxf/bus/extension/ExtensionManagerBus.java#L68-L72

Even though Serdal's answer is correct, it does not look practical to me.
My solution
I removed org.apache.cxf.logging.enabled system property and used following code to enable SOAP logging:
Client client = ClientProxy.getClient(port);
LoggingInInterceptor inInterceptor = new LoggingInInterceptor();
inInterceptor.setPrettyLogging(true);
client.getInInterceptors().add(inInterceptor);
LoggingOutInterceptor outInterceptor = new LoggingOutInterceptor();
outInterceptor.setPrettyLogging(true);
client.getOutInterceptors().add(outInterceptor);

I was able to pretty print and also to increase limit size of XML response from Webservice by doing the following:
wsdlLocationURL = new URL(productServiceURLStr);
ServiceFacadeBeanService serviceFacade =
new ServiceFacadeBeanService(wsdlLocationURL, SERVICE_FACADE_QNAME);
ServiceFacade sfPort = serviceFacade.getServiceFacadeBeanPort();
Client client = ClientProxy.getClient(sfPort);
List<Interceptor<? extends Message>> ics = client.getBus().getOutInterceptors();
for (Interceptor ic: ics) {
if (ic instanceof LoggingOutInterceptor) {
LoggingOutInterceptor out = (LoggingOutInterceptor) ic;
out.setPrettyLogging(true);
out.setLimit(1024 * 1024 *1024);
}
}

Use below mentioned annotations with your web service.
#InInterceptors(interceptors = "org.apache.cxf.interceptor.LoggingInInterceptor")
#OutInterceptors(interceptors = "org.apache.cxf.interceptor.LoggingOutInterceptor")
#InFaultInterceptors(interceptors = "org.apache.cxf.interceptor.LoggingInInterceptor")
#OutFaultInterceptors(interceptors = "org.apache.cxf.interceptor.LoggingOutInterceptor")
#Logging(pretty = true)

Related

Amazon DynamoDB Java SDK won't use proxy settings

I'm trying to implement an interface to AWS' DynamoDB in ColdFusion 11, on a corporate network with an NTLM proxy. I started with BDCraven's cfdynamo implementation, and extended it as per the SDK docs to include my proxy settings.
Component structure and init function below. getProxyParameters.cfm pulls my proxy settings from the database and initialises strProxyServer, strProxyPort etc. These proxy settings and credentials have been tested in other ColdFusion code (using cfhttp) and are definitely valid.
component accessors="true" alias="cfc.DynamoClient" displayname="DynamoClient" hint="I handle interactions with an Amazon DynamoDB instance"{
property name="aws_key" type="string" hint="The AWS Key";
property name="aws_secret" type="string" hint="The AWS Secret";
property name="aws_creds" type="object";
property name="aws_dynamodb" type="object";
include "/getProxyParameters.cfm";
variables.aws_key = "";
variables.aws_secret = "";
public cfc.DynamoClient function init(required string aws_key, required string aws_secret){
variables.aws_key = trim(arguments.aws_key);
variables.aws_secret = trim(arguments.aws_secret);
variables.aws_creds = createObject("java","com.amazonaws.auth.BasicAWSCredentials").init(variables.aws_key, variables.aws_secret);
aws_clientconfig = createObject("java","com.amazonaws.ClientConfiguration").init();
aws_clientconfig.setProtocol(createObject("java","com.amazonaws.Protocol").HTTPS);
aws_clientconfig.setProxyHost(strProxyServer);
aws_clientconfig.setProxyPort(strProxyPort);
aws_clientconfig.setProxyUsername(strProxyUsername);
aws_clientconfig.setProxyPassword(strProxyPassword);
aws_clientconfig.setProxyDomain(strProxyDomain);
variables.aws_dynamodb = createObject("java","com.amazonaws.services.dynamodb.AmazonDynamoDBClient").init(aws_creds, aws_clientconfig);
variables.aws_dynamodb.setEndpoint('dynamodb.ap-southeast-2.amazonaws.com');
variables.aws_dynamodb.setConfiguration(aws_clientconfig);
return this;
}
[...etc]
This init function returns without error, and variables.aws_dynamodb is an object of type com.amazonaws.services.dynamodb.AmazonDynamoDBClient.
The problem is that when I try to use it, the proxy settings are ignored:
public array function list_tables(string start_table, numeric limit=1){
var table_request = createObject("java","com.amazonaws.services.dynamodb.model.ListTablesRequest").init();
table_request.setLimit(arguments.limit);
if(structKeyExists(arguments,"start_table")){
table_request.setExcusiveStartTableName(trim(arguments.start_table));
}
return variables.aws_dynamodb.listTables(table_request).getTableNames();
}
This list_tables function waits for a long time, and then returns a ColdFusion error:
I've tried running netstat -a on the server while this request is happening, and the only connection is this SYN_SENT:
...and that IP looks like one of AWS's servers, not my proxy. Am I missing something obvious? Has anyone gotten this combination of tech to work properly?

Trouble with SOAP request from Flex

SUM: I ended up having to form the XML manually. I also had to create an Operation and use its send(); method rather than just doing something like WebService.MyServiceFunction(); - not sure why that was the case.
I send off the request as follows:
var xm:XML =
<SetPropertiesForCurrentUser xmlns="http://asp.net/ApplicationServices/v200">
<values xmlns:d4p1="http://schemas.microsoft.com/2003/10/Serialization/Arrays" xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
<d4p1:KeyValueOfstringanyType>
<d4p1:Key>{obj.Key}</d4p1:Key>
<d4p1:Value xmlns:d6p1="http://www.w3.org/2001/XMLSchema" i:type="d6p1:string">{obj.Value}</d4p1:Value>
</d4p1:KeyValueOfstringanyType>
</values>
</SetPropertiesForCurrentUser>;
var profileService:WebService = new WebService();
profileService.useProxy = false;
profileService.loadWSDL(url);
var o:Operation = profileService.SetPropertiesForCurrentUser;
o.send(xm);
Here’s my scenario:
I have ASP.NET web services to handle authentication, user roles, and user profiles (default ASP.NET AuthenticationService, RoleService, and ProfileService, to be exact).
So from my Flex web app, I am able to successfully call the ASP.NET service. For example, something like this works fine:
var profileService:WebService = new WebService();
profileService.useProxy = false;
profileService.GetAllPropertiesForCurrentUser.addEventListener("result",getAllPropertiesForCurrentUser_EventHandler);
profileService.addEventListener("fault",getAllPropertiesForCurrentUserFault_EventHandler);
profileService.loadWSDL(url);
profileService.GetAllPropertiesForCurrentUser();
I run into trouble when I need to pass a Dictionary object to another function on the service (SetPropertiesForCurrentUser). The .NET service asks for this type of value:
System.Collections.Generic.IDictionary(Of String, Object)
Here are the two pertinent entries from the web.config entry from my ASP.NET service:
<properties>
<clear/>
<add name="coordinateFormat" />
</properties>
...
<profileService enabled="true"
readAccessProperties="coordinateFormat"
writeAccessProperties="coordinateFormat"/>
So after putting together a SOAP request from a Silverlight app (which works as expected) I’ve narrowed it down to a difference in the XML request sent to the SOAP handler:
From Flex:
<tns:Value>DMS</tns:Value>
From Silverlight:
<d4p1:Value xmlns:d6p1="http://www.w3.org/2001/XMLSchema" i:type="d6p1:string">DMS</d4p1:Value>
If I take the request generated by Flex, catch it with Fiddler, modify that one line to include the “type” namespace – it works.
Anyone have an idea how I can get that namespace onto my variable that is passed to the SOAP handler from Actionscript? Here is my code for sending off that SetPropertiesForCurrentUser function:
var obj:Object = {};
obj["Key"] = "coordinateFormat";
obj["Value"] = DMS;
var profileService:WebService = new WebService();
profileService.useProxy = false;
profileService.SetPropertiesForCurrentUser.addEventListener("result",setPropertiesForCurrentUser_EventHandler);
profileService.addEventListener("fault",setPropertiesForCurrentUserFault_EventHandler);
profileService.loadWSDL(url);
profileService.SetPropertiesForCurrentUser(new ArrayCollection([obj]),false);
Thanks,
Josh
The default SOAPEncoder that is used is some what limited in its capabilities (like not including the type attribute you mentioned above). Luckily, there is a way to control that by writing your own encoder.
see this link at adobe (read part about using custom web service serialization) Link on Adobe's Site

Unable to set headers in apex web service callouts in salesforce

I'm currently trying to call Amazon Product Retail Web Service in Salesforce.
As I mentioned in
Getting WSDL parse error while generating Apex code from WSDL in Salesforce
I was initially unable to generate apex stub class, but I followed the method suggested by #Ballinger and created apex class. I wrote an apex class to use that stub and to set request parameters. The class i wrote is as follows
public class AmazonProductStubNew
{
public static void getResults()
{
System.Debug(' getResults start ');
AmazonWS.AWSECommerceServicePortUS stub = new AmazonWS.AWSECommerceServicePortUS();
stub.inputHttpHeaders_x = new Map<String,String>();
stub.inputHttpHeaders_x.put('AWSAccessKeyId','MyAmazonAWSAccessKeyId');
stub.inputHttpHeaders_x.put('Timestamp','2012-11-28T12:11:30Z');
stub.inputHttpHeaders_x.put('Signature','Encrypted Secret Code');
String MarketplaceDomain = '';
String AWSAccessKeyId = 'MyAmazonAWSAccessKeyId';
String AssociateTag = '';
String XMLEscaping = '';
String Validate = '';
AmazonWS.ItemSearchRequest Shared = new AmazonWS.ItemSearchRequest();
Shared.SearchIndex = 'DVD';
AmazonWS.ItemSearchRequest[] Request = new AmazonWS.ItemSearchRequest[1];
Request[0] = new AmazonWS.ItemSearchRequest();
Request[0].Title = 'Inception';
AmazonWS.ItemSearchResponse_element response = stub.ItemSearch(MarketplaceDomain,AWSAccessKeyId,AssociateTag,XMLEscaping,Validate,Shared,Request);
AmazonWS.Items_element[] localItems = response.Items;
System.Debug(localItems[0].TotalResults);
}
}
Even though I've added HTTP headers to stub, I'm not getting it in XML Request message
XML Request is as follows
<?xml version="1.0" encoding="UTF-8"?>
<env:Envelope xmlns:env="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<env:Header />
<env:Body>
<ItemSearch xmlns="http://webservices.amazon.com/AWSECommerceService/2011-08-01">
<MarketplaceDomain>
</MarketplaceDomain>
<AWSAccessKeyId>MyAWSAccessKeyId</AWSAccessKeyId>
<AssociateTag></AssociateTag>
<XMLEscaping></XMLEscaping>
<Validate></Validate>
<Shared><SearchIndex>DVD</SearchIndex></Shared>
<Request><Title>Inception</Title>
</Request></ItemSearch>
</env:Body></env:Envelope>
Since headers are not there in SOAP Request, There is a SOAP fault asking for Signature from Amazon Server.
As you can see, I'm new to Salesforce Apex. I followed the steps in
http://www.salesforce.com/us/developer/docs/apexcode/index_Left.htm#StartTopic=Content/apex_web_services_wsdl2apex.htm#http_header_support
to set the headers.
Any idea on why the header isn't getting added?
P.S I added headers manually and tried in SOAP UI, I'm getting proper response.
Thanks :)
I think you're using wrong functions :) (question is indeed confusing).
SOAP (or generally HTTP) communication consists of sending headers and actual message (payload if you like). Headers are short text thingies, message is often a giant XML.
Your code is setting HTTP headers (which are used in web communication to authenticate, provide info about your browser, preferred languages, set cookies, return status codes like 404 page not found...) Please don't be offended with the "for dummies" but I realize the wikipedia article is a bit too much, this might be simpler: http://net.tutsplus.com/tutorials/other/http-headers-for-dummies/
And what I suspect Amazon's webservice wants is just some fields inside the <env:Header>...</env:Header> tag? Just check the generated apex code for existence of subclass called "Header" (you can also search for the variable names like "Signature". This is going to be a total wild guess but I think you'll have to write something like that:
AmazonWS.AWSECommerceServicePortUS stub = new AmazonWS.AWSECommerceServicePortUS();
AmazonWS.Header h = new AmazonWS.Header();
h.AWSAccessKeyId = 'MyAmazonAWSAccessKeyId';
h.Timestamp = '2012-11-28T12:11:30Z';
h.Signature = 'Encrypted Secret Code';
stub.Header = h; // plug it into the request
// create and plug other required tags
AmazonWS.ItemSearchRequest Shared = new AmazonWS.ItemSearchRequest();
Shared.SearchIndex = 'DVD';
AmazonWS.ItemSearchRequest[] Request = new AmazonWS.ItemSearchRequest[1];
Request[0] = new AmazonWS.ItemSearchRequest();
Request[0].Title = 'Inception';
// ...
Now, to make it more confusing you might still have to use a HTTP header, there's a special one called SOAPAction. But generally speaking I believe you're after placing your data in the XML, not in http headers.
Funny enough, I've downloaded the Java example from http://aws.amazon.com/code/Product-Advertising-API/2478 and if I read it correctly they're passing the signature in the URL (endpoint), not in the XML. Probably because it's a REST GET method (if you can access that API it could save you a lot of hair pulled, SOAP is clunky).

Create a web service with CodeIgniter

im using CodeIgniter 1.7 framework to make my Website.
Another team do the mobile version for iPhone.
So the other team ask me to do a web service for authentification.
They tell that they will send me :
POST REQUEST
Input : login , password, push_token
if failure authentification -> Output HTTP : error code 0
if success -> Output XML :
<DATA>
<User id='id_user' title='..' first_name='' last_name='' email='' postal='' country_id=''/>
</DATA>
Basically i have this function for authentification:
function check_login($username="", $password="")
{
$username = $_POST['username'];
$password = $_POST['password'];
...
...
}
im looking into this post Codeigniter web services but i don't understand how its really work because im new in webservice.
I would consider using json as a sole output with one value being TRUE or FALSE depending on success. It's easier to handle, and all it requires is for your site to be in utf8.
If your check_login() returns TRUE, use that as the condition for success.
Example of reply:
/* Class etc. */
function do_login() {
$arr_json = array('success' => FALSE);
if ($this->login_library->check_login()) {
$arr_json['success'] = TRUE;
$arr_json['user_id'] = $this->login_library->user_id;
}
echo json_encode($arr_json);
}
login_library is just an example for your library which does the login. The reply they receive only needs to be decoded through json_decode(). And then simply check if the key success is TRUE or not.
If needed, have an extra key called error_message or similiar, and you can run all post-values through form_validation. Then you can also have $arr_json['error_message'] = trim(validation_errors('', "\n")); before the echo aswell.
You should definately look into Phil Sturgeons CodeIgniter Rest Server:
https://github.com/philsturgeon/codeigniter-restserver
There's a pretty good documentation. He also made a screencast about it: http://philsturgeon.co.uk/blog/2011/03/video-set-up-a-rest-api-with-codeigniter
Furthermore you could have a look at this article, where Adam Whitney explains his approach:
Building a RESTful Service using CodeIgniter
http://adamwhitney.net/blog/?p=707

Dynamic web service request

I'm trying to dynamically send a SOAP request to different webservices. Each webservice has its own ID, so I just basically have to change the ID of the webservice in the URL, E.G.:
http://mywebservice.com/ID/servicedosomething
Anyway, I don't know how to do this manually. I can't reference the services because I would have to add a lot of web references into the app, which doesn't seem very good to do.
Anyway, I just want to know how to construct the SOAP request, send it, and get the result from the service. Btw, I've checked other solutions to similar questions and none worked for me, might be the WP7 framework or something.
Thanks!
From my experience, it is very easy to design and build Windows Phone applications with RESTful web services. In a situation where you only have SOAP XML web services to work with, you will need to do some work within the application to prepare the request, send it and parse the response.
You can store the webservice URL as a string "template" like so -
string wsUrlTemplate = "http://mywebservice.com/{0}/servicedosomething";
When you are about to issue a request, just format the string -
string wsUrl = string.Format(wsUrlTemplate, webServiceID);
If you have the SOAP XML request format, then store it as a template. When you need to issue the request, replace the placeholders with the actual values and send the request (with a POST option, if thats what the web services expect). A typical SOAP XML request template may look like -
string xmlRequestTemplate = "
<?xml version="1.0" encoding="utf-8" ?>
<Customer>
<CustomerID>{0}</Customer>
</Customer>"
To prepare the request XML, you adopt the same approach as above - string format the xmlRequestTemplate and add the CustomerID. To issue the request, use HttpWebRequest to asynchronously issue the request and in the response handler, parse the XML response.
var request = HttpWebRequest.Create(wsUrl);
var result = (IAsyncResult)request.BeginGetResponse(ResponseCallback, request);
private void ResponseCallback(IAsyncResult result)
{
var request = (HttpWebRequest)result.AsyncState;
var response = request.EndGetResponse(result);
using (var stream = response.GetResponseStream())
using (var reader = new StreamReader(stream))
{
var contents = reader.ReadToEnd();
// Parse the XML response
}
}
Hope this gives you some ideas to proceed.
indyfromoz