Archive for April 2009
Oracle JDBC Driver and Spring 2.0.X Timestamp issue
Oracle JDBC Driver (ojdbc14.jar)
import org.springframework.jdbc.support.rowset.SqlRowSet;
public class QueryDAO extends JdbcDaoSupport {
public SqlRowSet loadSqlRowSet(String sSQL) {
return getJdbcTemplate().queryForRowSet(sSQL);
}
}
Using Spring JDBC in such way Timestamp fields are recovered without time information (hours, minutes and seconds set to 0). It seems some issue relative to Sun or Oracle, but there is a workaround in order to achieve desired result.
SqlRowSet rset =
jdbcTemplate.queryForRowSet("select cast(sysdate as timestamp) from dual");
while (rset.next()) {
System.out.println("-> " +
((oracle.sql.TIMESTAMP)rset.getObject(1)).timestampValue());
}
Our batch process failed last night because of this…
Spring WS 1.0 using Castor 1.1.1 marshalling (force UTF-8 encoding)
While XMLBeans performs marshalling operations using UTF-8 encoding by default, Castor XML relies on implicit Stream encoding. So, it’s mandatory to set UTF-8 encoding when using Castor marshalling on a Web Services client.
Below a Spring WS web service client sample using XWSS 3.0 is exposed. Spring’s application context (applicationContext.xml) and XWSS security policy file (wss-client-config.xml) are required (Spring WS Client).
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import javax.xml.soap.SOAPMessage;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.Resource;
import org.springframework.oxm.castor.CastorMarshaller;
import org.springframework.ws.WebServiceMessage;
import org.springframework.ws.client.core.WebServiceMessageCallback;
import org.springframework.ws.client.core.WebServiceTemplate;
import org.springframework.ws.client.core.support.WebServiceGatewaySupport;
import org.springframework.ws.soap.saaj.SaajSoapMessage;
import org.springframework.ws.soap.security.xwss.XwsSecuritySecurementException;
import org.springframework.ws.soap.security.xwss.callback.KeyStoreCallbackHandler;
import com.sun.xml.wss.ProcessingContext;
import com.sun.xml.wss.XWSSProcessor;
import com.sun.xml.wss.XWSSProcessorFactory;
import com.sun.xml.wss.XWSSecurityException;
public class WSCastorClient extends WebServiceGatewaySupport {
// XWSS supporting objects
private static XWSSProcessor cprocessor;
private KeyStoreCallbackHandler ksch;
/**
* Get the keystore
* @return
*/
public KeyStoreCallbackHandler getKsch() {
return ksch;
}
/**
* Set the keystore
* @param ksch
*/
public void setKsch(KeyStoreCallbackHandler ksch) {
this.ksch = ksch;
}
/**
* Default constructor.
*
* @param ksch Keystore
* @param castorMarshaller Castor marshaller
* @param castorUnmarshaller Castor unmarshaller
*/
public WSCastorClient(KeyStoreCallbackHandler ksch, CastorMarshaller castorMarshaller, CastorMarshaller castorUnmarshaller) {
this.ksch = ksch;
this.setMarshaller(castorMarshaller);
this.setUnmarshaller(castorUnmarshaller);
}
/**
* Invokes a web service using defaultUri
*
* @param the unnmarshalled message payload as object
*
* @return the object to be marshalled as response
*/
private Object callWs(Object input) {
WebServiceTemplate wst = getWebServiceTemplate();
wst.setMarshaller(getMarshaller());
wst.setUnmarshaller(getUnmarshaller());
Object result = wst.marshalSendAndReceive(input,
new WebServiceMessageCallback() {
public void doWithMessage(WebServiceMessage message) throws IOException {
SaajSoapMessage saajSoapMessage = (SaajSoapMessage) message;
// UTF-8 encoding
try {
ByteArrayOutputStream os = new ByteArrayOutputStream();
message.writeTo(os);
StringBuilder sm = new StringBuilder(os.toString());
os.close();
ByteArrayInputStream is = new ByteArrayInputStream(sm.toString().getBytes("UTF-8"));
SaajSoapMessage wsm = (SaajSoapMessage)getWebServiceTemplate().getMessageFactory().createWebServiceMessage(is);
saajSoapMessage.setSaajMessage(wsm.getSaajMessage());
is.close();
} catch (Exception e) {
e.printStackTrace();
}
// Do WSS signature
SOAPMessage saajMessage = saajSoapMessage.getSaajMessage();
try {
ProcessingContext context = new ProcessingContext();
context.setSOAPMessage(saajMessage);
SOAPMessage securedMessage = cprocessor.secureOutboundMessage(context);
saajSoapMessage.setSaajMessage(securedMessage);
} catch (XWSSecurityException e) {
throw new XwsSecuritySecurementException(e.getMessage());
}
}
});
return result;
}
/**
* Invoke web service
* @param opeRequest
* @param invoker
* @return
*/
public static Object invoke(Object opeRequest, Class invoker) {
// Application Context load
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml", invoker);
// XWSS parameters
Resource xwssConfig = new ClassPathResource("wss-client-config.xml", invoker);
// XWSS client
WSCastorClient xwssClient = (WSCastorClient) applicationContext.getBean("wsCastorClient");
Object ret = null;
try {
// XWSS initializacion
XWSSProcessorFactory factory = XWSSProcessorFactory.newInstance();
cprocessor = factory.createProcessorForSecurityConfiguration(xwssConfig.getInputStream(), xwssClient.getKsch());
// Web service invocation
ret = xwssClient.callWs(opeRequest);
} catch (Exception e) {
e.printStackTrace();
}
// response
return ret;
}
}
Upload file to Microsoft Office Sharepoint Server 2007
Microsoft Office Sharepoint Server 2007 (aka MOSS2007) provides a web services catalog in order to perform a large collection of operations on it. Morever, if enabled, WebDAV access is available.
The obvious way to upload a file to MOSS Shared Documents is the use of WebDAV protocol, however Microsoft includes a web service to perform this operation additionally. Below, both methods are shown.
Using WebDAV protocol
Required libraries: commons-httpclient-3.1.jar, commons-codec-1.3.jar, commons-logging-1.1.1.jar, log4j-1.2.15.jar, slf4j-api-1.5.6.jar, slf4j-log4j12-1.5.6.jar, jackrabbit-webdav-1.4.jar
import java.io.File;
import java.io.FileInputStream;
import org.apache.commons.httpclient.Credentials;
import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.NTCredentials;
import org.apache.commons.httpclient.UsernamePasswordCredentials;
import org.apache.commons.httpclient.auth.AuthScope;
import org.apache.commons.httpclient.methods.InputStreamRequestEntity;
import org.apache.commons.httpclient.methods.RequestEntity;
import org.apache.jackrabbit.webdav.client.methods.PutMethod;
public class UploadFileMOSSWebDAV {
// Proxy parameters
static String proxyHost = "proxy.server.com";
static Integer proxyPort = 80;
static String proxyUser = "user";
static String proxyPass = "pass";
// Sharepoint parameters
static String sharepointUser = "user";
static String sharepointPass = "pass";
static String sharepointDomain = "DOMAIN";
// Shared Documents folder root
static String sharedDocumentsRoot = "http://sharepoint.server.com/sites/IdSite/Shared Documents/";
/**
* Note: Setting credentials with AuthScope.ANY authentication scope (null value for host and/or realm) is
* highly discouraged in production applications.
* @param args
* @throws Exception
*/
public static void main(String... args) throws Exception {
// HTTP client with authentication enabled
HttpClient client = new HttpClient();
client.getParams().setAuthenticationPreemptive(true);
// Proxy configuration
client.getHostConfiguration().setProxy(proxyHost, proxyPort);
client.getState().setProxyCredentials(AuthScope.ANY,
new UsernamePasswordCredentials(proxyUser, proxyPass));
// Sharepoint authentication
Credentials defaultcreds =
new NTCredentials(sharepointUser, sharepointPass, "localhost", sharepointDomain);
client.getState().setCredentials(AuthScope.ANY, defaultcreds);
// Upload local file test.txt to sharedDocumentsRoot/SomeFolder/test.txt
PutMethod method = new PutMethod(sharedDocumentsRoot + "SomeFolder/test.txt");
RequestEntity requestEntity =
new InputStreamRequestEntity(new FileInputStream(new File("c:/temp/test.txt")));
method.setRequestEntity(requestEntity);
client.executeMethod(method);
System.out.println(method.getStatusCode() + " "+ method.getStatusText());
}
}
Using MOSS Copy web service
Required libraries: commons-httpclient-3.1.jar, commons-codec-1.3.jar, commons-logging-1.1.1.jar, log4j-1.2.15.jar, activation-1.1.1.jar, saaj-api-1.3.jar, saaj-impl-1.3.2.jar, spring-core-2.5.6.jar, spring-context-2.5.6.jar, spring-beans-2.5.6.jar, spring-oxm-1.5.6.jar, spring-ws-core-1.5.6.jar, spring-xml-1.5.6.jar, xmlbeans tool
Resources: Getting started with Sharepoint Web Services
1. Retrieve WSDL from Sharepoint
WSDL for Copy web service can be found at http://sharepoint.server.com/sites/IdSite/_vti_bin/Copy.asmx?WSDL
2. Extract XSD from WSDL
Extract “s:schema” node from WSDL and include namespaces on root element
< ?xml version="1.0" encoding="utf-8"?>
<s_schema xmlns_s="http://www.w3.org/2001/XMLSchema"
xmlns_tns="http://schemas.microsoft.com/sharepoint/soap/"
elementFormDefault="qualified"
targetNamespace="http://schemas.microsoft.com/sharepoint/soap/">
[...]
</s_schema>
Note. “:” replaced by “_” for visualization.
3. Generate XMLBeans objects for marshal
Use XMLBeans Ant Task to generate Java objects in order to perform marshalling and unmarshalling operations from XML
4. Web service client
import java.io.File;
import java.io.FileInputStream;
import org.apache.commons.httpclient.Credentials;
import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.NTCredentials;
import org.apache.commons.httpclient.UsernamePasswordCredentials;
import org.apache.commons.httpclient.auth.AuthScope;
import org.apache.xmlbeans.XmlObject;
import org.apache.xmlbeans.impl.util.Base64;
import org.springframework.oxm.xmlbeans.XmlBeansMarshaller;
import org.springframework.ws.client.core.WebServiceTemplate;
import org.springframework.ws.client.core.support.WebServiceGatewaySupport;
import org.springframework.ws.soap.client.core.SoapActionCallback;
import org.springframework.ws.transport.http.CommonsHttpMessageSender;
import com.microsoft.schemas.sharepoint.soap.CopyIntoItemsDocument;
import com.microsoft.schemas.sharepoint.soap.DestinationUrlCollection;
import com.microsoft.schemas.sharepoint.soap.CopyIntoItemsDocument.CopyIntoItems;
public class UploadFileMOSSWS extends WebServiceGatewaySupport {
// Proxy parameters
static String proxyHost = "proxy.server.com";
static Integer proxyPort = 80;
static String proxyUser = "user";
static String proxyPass = "pass";
// Sharepoint parameters
static String sharepointUser = "user";
static String sharepointPass = "pass";
static String sharepointDomain = "DOMAIN";
// Shared Documents folder root
static String sharedDocumentsRoot = "http://sharepoint.server.com/sites/IdSite/Shared Documents/";
// WS Uri
static String defaultWSUri = "http://sharepoint.server.com/sites/IdSite/_vti_bin/Copy.asmx";
/**
* Note: Setting credentials with AuthScope.ANY authentication scope (null value for host and/or realm) is
* highly discouraged in production applications.
* @param args
* @throws Exception
*/
public static void main(String... args) throws Exception {
// XMLBeans request object
CopyIntoItemsDocument request = CopyIntoItemsDocument.Factory.newInstance();
CopyIntoItems cii = request.addNewCopyIntoItems();
DestinationUrlCollection duc = DestinationUrlCollection.Factory.newInstance();
duc.addNewString().setStringValue(sharedDocumentsRoot + "SomeFolder/test.txt");
cii.setDestinationUrls(duc);
cii.addNewFields().addNewFieldInformation();
// Sample file
String fileContent = "";
FileInputStream fis = new FileInputStream(new File("c:/temp/test.txt"));
while (fis.available() > 0) {
byte[] buffer = new byte[fis.available()];
fis.read(buffer);
fileContent = fileContent + new String(buffer);
}
cii.setStream(Base64.encode(fileContent.getBytes()));
// MOSS WS Copy File invocation with SOAP Action CopyIntoItems
System.out.println(new UploadFileMOSSWS().
callWs(request, "http://schemas.microsoft.com/sharepoint/soap/CopyIntoItems"));
}
/**
* Generic Spring WS Client
* @param input
* @param soapAction
* @return
*/
private XmlObject callWs(XmlObject input, String soapAction) {
XmlObject result = null;
// WS Client
WebServiceTemplate wst = getWebServiceTemplate();
XmlBeansMarshaller marshaller = new XmlBeansMarshaller();
wst.setMarshaller(marshaller);
wst.setUnmarshaller(marshaller);
wst.setDefaultUri(defaultWSUri);
// HTTP Client configuration
HttpClient client = new HttpClient();
client.getParams().setAuthenticationPreemptive(true);
client.getHostConfiguration().setProxy(proxyHost, proxyPort);
client.getState().setProxyCredentials(AuthScope.ANY,
new UsernamePasswordCredentials(proxyUser, proxyPass));
Credentials defaultcreds =
new NTCredentials(sharepointUser, sharepointPass, "localhost", sharepointDomain);
client.getState().setCredentials(AuthScope.ANY, defaultcreds);
CommonsHttpMessageSender messageSender = new CommonsHttpMessageSender(client);
wst.setMessageSender(messageSender);
// WS invocation with SOAP Action
result = (XmlObject)wst.marshalSendAndReceive(input, new SoapActionCallback(soapAction));
return result;
}
}