martes 6 de octubre de 2009

Accediendo a Report Server de MS desde Java con Axis2

Con Axis2 el código se reduce y se hace mas legible:

import javax.activation.DataHandler;

import org.apache.commons.io.IOUtils;

import com.microsoft.schemas.sqlserver._2005._06._30.reporting.reportingservices.ReportExecutionServiceStub;
import com.microsoft.schemas.sqlserver._2005._06._30.reporting.reportingservices.ReportExecutionServiceStub.ExecutionHeader;
import com.microsoft.schemas.sqlserver._2005._06._30.reporting.reportingservices.ReportExecutionServiceStub.ExecutionHeaderE;
import com.microsoft.schemas.sqlserver._2005._06._30.reporting.reportingservices.ReportExecutionServiceStub.LoadReport;
import com.microsoft.schemas.sqlserver._2005._06._30.reporting.reportingservices.ReportExecutionServiceStub.LoadReportResponse;
import com.microsoft.schemas.sqlserver._2005._06._30.reporting.reportingservices.ReportExecutionServiceStub.Render;
import com.microsoft.schemas.sqlserver._2005._06._30.reporting.reportingservices.ReportExecutionServiceStub.RenderResponse;

public class Test {
public String getReport() throws Exception{
ReportExecutionServiceStub re = new ReportExecutionServiceStub(null,"http://localhost/ReportServer/ReportExecution2005.asmx");
LoadReport loadReport76= new LoadReport();

loadReport76.setReport("/ruta/al/report");
loadReport76.setHistoryID(null);

LoadReportResponse LRepResp= re.loadReport(loadReport76, null);
String ID= LRepResp.getExecutionInfo().getExecutionID();
ExecutionHeaderE executionHeader73=new ExecutionHeaderE();

ExecutionHeader param= new ExecutionHeader();
param.setExecutionID(ID);
executionHeader73.setExecutionHeader(param);

Render render47= new Render();
render47.setDeviceInfo("<DeviceInfo><Toolbar>False</Toolbar></DeviceInfo>");
render47.setFormat("XML");

RenderResponse respuesta=re.render(render47, executionHeader73, null);
DataHandler dh=respuesta.getResult();

String xml = IOUtils.toString(dh.getInputStream());


return xml;
}
}


Las clases necesarias para el cliente fueron generadas con el WTP de eclipse con el entorno Axis 2 configurado.
Aqui se puede descargar el ssrsExecutionService.jar generado por axis2.

lunes 5 de octubre de 2009

Accediendo a Report Server de MS desde Java con Axis

Después de pegarme durante horas con los servicios web de Reporting Services de MS y sufrir como siempre las exquisiteces de .NET he decidido publicar el código en java con axis(Autogenerado desde WTP de eclipse) con la modificación de las cabeceras SOAP necesarias para el servicio devuelva el informe.

import java.net.URL;

import javax.xml.rpc.holders.ByteArrayHolder;
import javax.xml.rpc.holders.StringHolder;
import javax.xml.soap.SOAPElement;

import org.apache.axis.AxisFault;
import org.apache.axis.message.SOAPHeaderElement;

import com.microsoft.schemas.sqlserver._2005._06._30.reporting.reportingservices.ExecutionInfo;
import com.microsoft.schemas.sqlserver._2005._06._30.reporting.reportingservices.ReportExecutionServiceSoapStub;
import com.microsoft.schemas.sqlserver._2005._06._30.reporting.reportingservices.ReportingService2005SoapStub;
import com.microsoft.schemas.sqlserver._2005._06._30.reporting.reportingservices.holders.ArrayOfStringHolder;
import com.microsoft.schemas.sqlserver._2005._06._30.reporting.reportingservices.holders.ArrayOfWarningHolder;
public class reportingClient {

/**
* @param args
* @throws AxisFault
* @throws Exception
*/
public static void main(String[] args) throws AxisFault, Exception {
// TODO Auto-generated method stub

ReportingService2005SoapStub rs = new ReportingService2005SoapStub(new URL("http://localhost/ReportServer/ReportService2005.asmx"), null);
ReportExecutionServiceSoapStub re = new ReportExecutionServiceSoapStub(new URL("http://localhost/ReportServer/ReportExecution2005.asmx"),null);

//ejecutamos el informe
ExecutionInfo EInfo=re.loadReport("/tu/ruta/al/report", null);
//¿necesitamos algun parametro o una credencial? esperemos que no.
System.out.println(EInfo.isParametersRequired());
System.out.println(EInfo.isCredentialsRequired());

//load report and get executionID
//lo mas dificil ha sido meter las cabeceras para que MS pillara el id de ejecucion
//
SOAPHeaderElement header = new SOAPHeaderElement("http://schemas.microsoft.com/sqlserver/2005/06/30/reporting/reportingservices", "ExecutionHeader");
SOAPElement se = header.addChildElement("ExecutionID").addTextNode(EInfo.getExecutionID());
re.setHeader(header);
//fin set headers

//parametros de render
ByteArrayHolder result = new ByteArrayHolder();
StringHolder encoding=new StringHolder();
StringHolder mimeType=new StringHolder();
StringHolder extension=new StringHolder();
ArrayOfWarningHolder warnings=new ArrayOfWarningHolder();
ArrayOfStringHolder streamIds=new ArrayOfStringHolder();
//fin de parametros para render


re.render("XML", "False", result, extension, mimeType, encoding, warnings, streamIds);
System.out.write(result.value);
}
}


Espero que os sirva de algo y os ahorre tiempo.
Justo después de lograr conectar encontré un ejemplo en el MSDN de MS bastante parecido al mio. También encontré varios ejemplos con variantes en cuanto a la generación de las cabeceras.
Por cierto que el resultado del informe viene con estos bytes al inicio <?xml version="1.0" encoding="utf-8"?><Report... y que tiene que ver con la codificación del documento. Se puede leer mas info aquí

viernes 18 de septiembre de 2009

Crear un cliente Web services para Alfresco 3.2 desde eclipse.

Después de pelearme con el API java de los servicios web de Alfresco he decidido publicar algunos ejemplos de clientes que he programado.
Necesitamos descargar el API desde la dirección:
http://wiki.alfresco.com/wiki/Labs_3_Stable_download_files
Podemos descargar el SDK completo o simplemente las librerias de servicios web (Alfresco Web Service Client)
Abrimos eclipse y creamos un nuevo proyecto java

Agregamos las librerias del SDK al proyecto con click derecho propiedades -> Build Path-> Add External JARs

Y las librerias de la carpeta dependencies:

Si queremos programar más agusto podemos asociar el codigo fuente a alfresco-web-service-client.jar

Ahora es el momento de crear el cliente en este caso el cliente descargará un documento conociendo el uuid:

import org.alfresco.webservice.types.Predicate;
import org.alfresco.webservice.types.Reference;
import org.alfresco.webservice.content.Content;
import org.alfresco.webservice.content.ContentServiceSoapBindingStub;
import org.alfresco.webservice.types.Store;
import org.alfresco.webservice.util.AuthenticationUtils;
import org.alfresco.webservice.util.Constants;
import org.alfresco.webservice.util.ContentUtils;
import org.alfresco.webservice.util.WebServiceFactory;

public class Cliente {

private static final String USERNAME = "admin";
private static final String PASSWORD = "admin";

/**
* @param args
*/
public static void main(String[] args) throws Exception {

WebServiceFactory.setEndpointAddress("http://localhost/alfresco/api");
AuthenticationUtils.startSession(USERNAME, PASSWORD);
Store STORE = new Store(Constants.WORKSPACE_STORE, "SpacesStore");

// vamos a leer contenido del repositorio
ContentServiceSoapBindingStub contentService = WebServiceFactory
.getContentService();
Reference ref = new Reference();

ref.setStore(STORE);
ref.setUuid("51758149-66a4-4eb7-a500-15d5eed95030");
Content[] readResult = contentService.read(new Predicate(
new Reference[] { ref }, STORE, null), Constants.PROP_CONTENT);
Content content = readResult[0];

System.out.println("Contenido:");
System.out.println(ContentUtils.getContentAsString(content));

AuthenticationUtils.endSession();

}
}


Ejecutamos el cliente y nos devuelve el contenido del documento:

Contenido:
%PDF-1.4
%âãÏÓ
15 0 obj
........ etc


Uno de los problemas que tuve con el cliente fué que el timestamp de las cabeceras WS estaban desincronizadas con el servidor (Ubuntu en vmware server) así que reinicié el servidor y el cliente sincronice en ambos la hora y ya está.

<wsu:Timestamp xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" wsu:Id="Timestamp-4347180">

<wsu:Created>2009-09-18T09:07:12.288Z</wsu:Created>

<wsu:Expires>2009-09-18T09:12:12.288Z</wsu:Expires>

</wsu:Timestamp>

sábado 12 de septiembre de 2009

Tornado Web Server liberado bajo licencia Apache 2.0

Si os impresionan los números y sobre todo si es con python como es mi caso os gustará la liberación del servidor web que usan en friendfeed (Facebook) con unos test que dan miedo:

Esto tengo que probarlo.