function readOnly(count){ }
Starting November 20, the site will be set to read-only. On December 4, 2023,
forum discussions will move to the Trailblazer Community.
+ Start a Discussion
Ollie.ax81Ollie.ax81 

Error Adding Document

I had adding a document to a document folder working in version 3 and now it is not working with version 5.

Using Tomcat 5 and a web application, as well as a JUnit test script to exercise the following code.

public String CreateDocument(String docName, File doc, String description,
ID authorId, ID folderId) {
echo("CreateDocument");
echo("docName=" + docName);
echo("File doc=" + doc.toString());
echo("Description=" + description);
echo("authorId=" + authorId.getValue());
echo("folderId=" + folderId.getValue());

String retStatus = "Success";
int fileLength = (int) doc.length();
byte[] body = new byte[fileLength];

//Verify that we are already authenticated, if not
//call the login function to do so
if (!loggedIn) {
if (!login()) {
return "Bad SalesForce Login";
}
}
try {
FileInputStream fis = new FileInputStream(doc);
fileLength = fis.read(body);
} catch (FileNotFoundException e) {
retStatus = "Error Failed to CreateDocument:"
+ e.getLocalizedMessage();
e.printStackTrace();
return retStatus;
} catch (IOException e1) {
retStatus = "Error Failed to CreateDocument:"
+ e1.getLocalizedMessage();
e1.printStackTrace();
return retStatus;
}

if (authorId == null) {
//default to current user
authorId = this.loginResult.getUserId();
}

try {
Document document;
SObject[] accs = new SObject[1];
document = new Document();

document.setName(docName);
document.setBody(body);
document.setDescription(description);
document.setAuthorId(authorId);
document.setFolderId(folderId);

accs[0] = document;

//create the object(s) by sending the array to the web service
SaveResult[] sr = binding.create(accs);
for (int i = 0; i < sr.length; i++) {
SaveResult result = sr[i];
if (result.isSuccess()) {
retStatus = "Success Created Document " + docName;
this.setLastSFID(result.getId().getValue()); //stores sfid
// for saving
// to property
// of new
// document
} else {
Error[] ers = (Error[]) result.getErrors();
retStatus = "Error:";
for (int j = 0; j < ers.length; j++) {
Error error = ers[j];
retStatus += error.getMessage() + ";";
System.out.println("error.getStatusCode():"
+ error.getStatusCode());
echo(retStatus);
}
}
}
} catch (UnexpectedErrorFault uef) {
echo(uef.getExceptionMessage());
} catch (Exception ex) {
retStatus = "\nFailed to create folder, " + docName
+ ", error message was: \n" + ex.getMessage();
echo(retStatus);
}

return retStatus;
}

Everything is fine until I look at the SaveResult and see the error.

Here is the log for the applicable section.

SalesForceContentManager:CreateDocument
SalesForceContentManager:docName=enterprise.wsdl
SalesForceContentManager:File doc=C:\DOCUME~1\MICHAE~1\LOCALS~1\Temp\ajcs31224.tmp
SalesForceContentManagerescription=From SFCM
SalesForceContentManager:authorId=00530000000cyikAAA
SalesForceContentManager:folderId=00l30000000h0i0AAA
SalesForceContentManager:un=ollie@someplace.com
SalesForceContentManager:pw=LETMEIN
SalesForceContentManager:Creating the binding to the web service...
SalesForceContentManager:LOGGING IN NOW....
SalesForceContentManager:
The session id is: 3Zx8p0zhPhQtWnxCSu8vx2ghC1A3EoTCWdz56hjDXXKx26smrLqeI_BX1E97gD0qV8TI9e.M4mBvhyqgMvY5PzteaH1xyGi1
SalesForceContentManager:
The new server url is: https://na1-api.salesforce.com/services/Soap/c/5.0
SalesForceContentManager:
Getting server's timestamp...
SalesForceContentManager:Time stamp on server: May 20, 2005 10:17:42 PM GMT
error.getStatusCode():INVALID_TYPE_ON_FIELD_IN_RECORD
SalesForceContentManager:Error:Body: value not of required type: 10;

I can create Folders and other SObjects and as I said this was working a while ago.

I know its something simple but I dunno. The sforce code was generated by the eclipse wsdl plugin from the enterprise.wsdl generated and downloaded TODAY.

Thanks in advance for your help.

Ollie
SuperfellSuperfell
What version of Axis are you using? have you traced the request message to make sure that its correct ?
Ollie.ax81Ollie.ax81
Axis 1.1
Ollie.ax81Ollie.ax81
I am trying to get a client handler to log the messages

SforceServiceLocator locator = new SforceServiceLocator();
binding = (SoapBindingStub) locator.getSoap();
QName serviceName = locator.getServiceName();
Call call = (Call) locator.createCall(serviceName);
SOAPMonitor sm = new SOAPMonitor(); //my extension to BasicHandler that logs in and out msgs

call.setClientHandlers(sm, sm);
oginResult = binding.login(un, pw); //un = username, pw = password.

or should getSoap() come after call.setClientHandlers(sm,sm) I couldn't find any usage.

Ollie
SuperfellSuperfell
You'd have to ask the Axis folks that one, I always use a network sniffer, like the excellent SOAPScope www.mindreef.com
Ollie.ax81Ollie.ax81
yea but that doesn't help with https.

Can I change something to use plain old http? I tried changing the Soap_address to http:// but it got redirected to https://na1... anyway.
SuperfellSuperfell
the redirectUrl will be https:// but you can modify it to be http:// for testing.
Ollie.ax81Ollie.ax81
;-) Ok nice big tease, how do I modify the redirect that comes from sforce.com?

Let me guess. In the ServiceLocator I change the Soap_address from "https://www.salesforce.com" to "http://na1-sforce.salesforce.com" and avoid the redirect?

Message Edited by Ollie on 05-26-2005 04:40 PM

SuperfellSuperfell
if lr is a LoginResult, then its just

String newUrl = lr.getServerUrl().replace("https:", "http:");
instead of
String newUrl = lr/getServerUrl();
Ollie.ax81Ollie.ax81
Sorry Simon but that doesn't help at all. Where (what source from the generated client) would I find that instruction?

I am using the locator.getSoap() to get a binding and calling the loginResult = binding.login(un,pw)

I searched all the .java sources generated for sforce and found no hits on getServerUrl except in the LoginResult class, but since nothing else calls it, even modifying that location won't have any affect.
SuperfellSuperfell
After you call login you need all subsequent requests have to go to the serverUrl returned in the LoginResult object. Somewhere you are either reseting the endpoint URL on the proxy class, or creating a new one at the new URL, this is where you make the change.
Ollie.ax81Ollie.ax81
I found the proper place to put the setClientHandlers() and put in my own custom handler to log the message traffic.

in the SoapBindingStub I modified the following. (see Ollie's Insertion below)

private org.apache.axis.client.Call createCall() throws java.rmi.RemoteException {
try {
org.apache.axis.client.Call _call =
(org.apache.axis.client.Call) super.service.createCall();
if (super.maintainSessionSet) {
_call.setMaintainSession(super.maintainSession);
}
if (super.cachedUsername != null) {
_call.setUsername(super.cachedUsername);
}
if (super.cachedPassword != null) {
_call.setPassword(super.cachedPassword);
}
if (super.cachedEndpoint != null) {
_call.setTargetEndpointAddress(super.cachedEndpoint);
}
if (super.cachedTimeout != null) {
_call.setTimeout(super.cachedTimeout);
}
if (super.cachedPortName != null) {
_call.setPortName(super.cachedPortName);
}
java.util.Enumeration keys = super.cachedProperties.keys();
while (keys.hasMoreElements()) {
java.lang.String key = (java.lang.String) keys.nextElement();
_call.setProperty(key, super.cachedProperties.get(key));
}
// All the type mapping information is registered
// when the first call is made.
// The type mapping information is actually registered in
// the TypeMappingRegistry of the service, which
// is the reason why registration is only needed for the first call.
synchronized (this) {
if (firstCall()) {
// must set encoding style before registering serializers
_call.setEncodingStyle(null);
for (int i = 0; i < cachedSerFactories.size(); ++i) {
java.lang.Class cls = (java.lang.Class) cachedSerClasses.get(i);
javax.xml.namespace.QName qName =
(javax.xml.namespace.QName) cachedSerQNames.get(i);
java.lang.Class sf = (java.lang.Class)
cachedSerFactories.get(i);
java.lang.Class df = (java.lang.Class)
cachedDeserFactories.get(i);
_call.registerTypeMapping(cls, qName, sf, df, false);
}
}
}
//Ollie's Insertion
SOAPMonitor sm = new SOAPMonitor();
_call.setClientHandlers(sm, sm);
//Ollie's Insertion

return _call;
}
catch (java.lang.Throwable t) {
throw new org.apache.axis.AxisFault("Failure trying to get the Call object", t);
}
}

This allowed my SOAPMonitor to log the messages, identify the fault and let me clear the cause.

Here are the successful messages from the log. (condensed...)



I238rrIa0lvPirl1dv3xIzNVDY5aoXzBoSwjP4GcFX7FOWiiwK5n2dvdjLV.eCkk6yVh.yVrFwriKIxjwLbKBjteaH1xyGi1




ocument" xmlns:ns2="urn:sobject.enterprise.soap.sforce.com">

00530000000cyikAAA
Iw0KI1NhdCBKdW4gMDvUHJvL2xpYi9zZXJ2bGV0LTIuMy9zZXJ2bGV0LmphcjsNCg==



From SFCM
00l30000000h0i0AAA




Friday Success.txt








2005-05-27 16:25:01,531 DEBUG [http-8080-Processor22] salesforce.SOAPMonitor (SOAPMonitor.java:70) - :::SOAP Response:::






015300000001vjmAAA
true






Whew, I hope this helps someone else save some time.

Ollie
SuperfellSuperfell
So you fixed your problem ? although it forum swollowed most of the xml, it does look like the response message was a sucess. What was the problem?
Ollie.ax81Ollie.ax81
Yes this forum is not very code friendly.

The problem was in my attempt to propogate log4j logging down through the various code pieces, as opposed to cod pieces, I made a silly mistake and put a log.debug(this) in the Document() constructor....so the document never made it, and I didn't have logging setup to display the exception for the null pointer when log tried to log null.

When I did get my handler working I saw the body was null and that clued me to look along that chain and found the problem. It wasn't my code in building the create operation but the attempt to log it that caused the problem.

Thanks, I hope this helps someone else save some time.