Archive

Archive for March 26th, 2009

Como Instalar PHPJavaBride (Hola Mundo PHP-Java-Bridge)

March 26th, 2009

Introducción

Vamos a realizar una instalación básica del PHPJavaBridge, y a la vez llamar a una clase java que haga un Hola Mundo.

Pre requisitos

1. ApacheTomcat 5.5+
2. PHP y Apache instalados - phpinfo() corriendo.

Bajar PHP-Java-Bridge e instalar en Tomcat

Se lo puede bajar de http://php-java-bridge.sourceforge.net/pjb/download.php (Ojo si por ahí a cambiado el url hacer un google download phpjavabridge). Generalmente yo bajo el paquete binario.

Una vez en el sitio de download bajamos el archivo php-java-bridge_5.x.x_documentation.zip. Bajamos este por que esta mas completo aunque en este instante solo necesitamos el war file.

Descomprimimos el archivo y dentro de este encontraremos el archivo JavaBridge.war.

Copiamos JavaBridge.war al directorio webapps de tomcat.

A veces si uno esta en linux, cuando se levanta el tomcat, no se descomprime automáticamente el war. En este caso hechos mano del root user y descomprimimos manualmente el war file, convirtiéndolo primero a zip y luego descomprimir con el comando unzip JavaBridge.zip -d JavaBridge.

Ok, ahora levantamos el tomcat y nos vamos a la pagina http://localhost:8080/JavaBridge/test.php.

Si todo va bien, aparecerá la pagina de información de php que es generado por el método phpinfo() .

Enlace con servidor Apache http

Creamos el enlace con el siguiente comando:

ln -s /opt/apache-tomcat-5.5.27/webapps/JavaBridge /var/www/JavaBridge

Como verán, creamos un link a la carpeta donde se encuentra el JavaBridge dentro de tomcat en la carpeta principal de apache.

Ahora vamos al browser y abrimos: http://localhost/JavaBridge/test.php. Una vez mas, si to va bien aparece la pagina de información de php.

Hola Mundo desde java

public class HelloWorld {
    public String sayHello(){
        return "Hello World";
    }
}

Creamos la clase anterior, la compilamos y la copiamos la clase compilada a un folder dentro de /var/www. puede ser algo como testjava.

Java dice Hola a PHP :)

Ahora con el php :)

<?php require_once("../JavaBridge/java/Java.inc");?>
<?php
	java_require('/var/www/testjava');
	$helloWorld = new Java('HelloWorld');
	echo $helloWorld->sayHello()
?>

require_once, nos permite conectarnos con el java bridge.

java_require, nos permite definir el classpath. Aqui tenemos que declarar los paths donde se encuentran nuestras clases y librerias en jar.

new Java(), nos permite instanciar una clase java.

Y al final llamamos al método sayHello() que nos devuelve un string que luego es impreso por la funcion echo de php.

Bueno hasta aqui por hoy. Hasta la proxima. :)

Renan Huanca PHPJavaBridge

Reporte maestro-detalle usando JRXMLDatasource de JasperReports 3.1.2

March 26th, 2009
Comments Off

Introducción

Este es un ejemplo de como realizar un reporte maestro detalle usando JasperReports.
Vamos a generar un simple pdf con el detalle de una factura(Invoice).
También pueden ver Como usar el JRXmlDataSource de JasperReports 3.1.2, para una introducción al JRXmlDataSource.

Archivo XML de datos

bueno, esta es la parte mas simple. :)

(invoice.xml)

<?xml version="1.0" encoding="UTF-8"?>
 
<invoice>
    <invoiceNumber>BP-0123</invoiceNumber>
    <invoiceDate>03/01/2009</invoiceDate>
    <clientName>ACME INC</clientName>
    <clientId>BP102USA</clientId>
    <products>
        <product>
            <name>Iphone 6000G</name>
            <quantity>12</quantity>
            <amout>4000</amout>
        </product>
        <product>
            <name>Lenovo T61P</name>
            <quantity>5</quantity>
            <amout>7000</amout>
        </product>
        <product>
            <name>Xbox 123</name>
            <quantity>2</quantity>
            <amout>1000</amout>
        </product>
        <product>
            <name>GOLDPATH 1</name>
            <quantity>4</quantity>
            <amout>400</amout>
        </product>
    </products>
</invoice>

Como verán, solo definimos datos como, nombre del cliente y el detalle de los productos.

Creación de diseños invoice.jrxml y invoice-detail.jrxml

Tanto los diseños del reporte maestro y detalle son los mismos. Como el de detalle es el mas simple lo listare primero y luego el maestro.

(invoice-detail.jrxml)

<?xml version="1.0" encoding="UTF-8"  ?>
<!-- Created with iReport - A designer for JasperReports -->
<!DOCTYPE jasperReport PUBLIC "//JasperReports//DTD Report Design//EN" "http://jasperreports.sourceforge.net/dtds/jasperreport.dtd">
<jasperReport name="invoice-detail">
	<property name="ireport.scriptlethandling" value="0" />
	<property name="ireport.encoding" value="UTF-8" />
 
	<field name="name" class="java.lang.String">
		<fieldDescription><![CDATA[name]]></fieldDescription>
	</field>
	<field name="quantity" class="java.lang.String">
		<fieldDescription><![CDATA[quantity]]></fieldDescription>
	</field>
	<field name="amout" class="java.lang.Integer">
		<fieldDescription><![CDATA[amout]]></fieldDescription>
	</field>
 
	<variable name="totalAmount" class="java.lang.Integer" resetType="Report" calculation="Sum">
		<variableExpression><![CDATA[$F{amout}]]></variableExpression>
	</variable>
		<background>
			<band height="0"  isSplitAllowed="true" >
			</band>
		</background>
		<title>
			<band height="0"  isSplitAllowed="true" >
			</band>
		</title>
		<pageHeader>
			<band height="0"  isSplitAllowed="true" >
			</band>
		</pageHeader>
		<columnHeader>
			<band height="32"  isSplitAllowed="true" >
				<staticText>
					<reportElement
						x="15"
						y="8"
						width="192"
						height="18"
						key="staticText-1"/>
					<box></box>
					<textElement>
						<font isBold="true"/>
					</textElement>
				<text><![CDATA[Product Name]]></text>
				</staticText>
				<staticText>
					<reportElement
						x="228"
						y="8"
						width="131"
						height="18"
						key="staticText-2"/>
					<box></box>
					<textElement>
						<font isBold="true"/>
					</textElement>
				<text><![CDATA[Quantity]]></text>
				</staticText>
				<staticText>
					<reportElement
						x="381"
						y="8"
						width="108"
						height="18"
						key="staticText-3"/>
					<box></box>
					<textElement textAlignment="Right">
						<font isBold="true"/>
					</textElement>
				<text><![CDATA[Amout]]></text>
				</staticText>
			</band>
		</columnHeader>
		<detail>
			<band height="38"  isSplitAllowed="true" >
				<textField isStretchWithOverflow="false" isBlankWhenNull="false" evaluationTime="Now" hyperlinkType="None"  hyperlinkTarget="Self" >
					<reportElement
						x="15"
						y="11"
						width="192"
						height="18"
						key="textField"/>
					<box></box>
					<textElement>
						<font/>
					</textElement>
				<textFieldExpression   class="java.lang.String"><![CDATA[$F{name}]]></textFieldExpression>
				</textField>
				<textField isStretchWithOverflow="false" isBlankWhenNull="false" evaluationTime="Now" hyperlinkType="None"  hyperlinkTarget="Self" >
					<reportElement
						x="228"
						y="11"
						width="131"
						height="18"
						key="textField"/>
					<box></box>
					<textElement>
						<font/>
					</textElement>
				<textFieldExpression   class="java.lang.String"><![CDATA[$F{quantity}]]></textFieldExpression>
				</textField>
				<textField isStretchWithOverflow="false" pattern="¤ #,##0.00" isBlankWhenNull="false" evaluationTime="Now" hyperlinkType="None"  hyperlinkTarget="Self" >
					<reportElement
						x="381"
						y="11"
						width="108"
						height="18"
						key="textField"/>
					<box></box>
					<textElement textAlignment="Right">
						<font/>
					</textElement>
				<textFieldExpression   class="java.lang.Integer"><![CDATA[$F{amout}]]></textFieldExpression>
				</textField>
				<staticText>
					<reportElement
						x="492"
						y="14"
						width="31"
						height="14"
						key="staticText-4"/>
					<box></box>
					<textElement>
						<font size="8"/>
					</textElement>
				<text><![CDATA[USD]]></text>
				</staticText>
			</band>
		</detail>
		<columnFooter>
			<band height="0"  isSplitAllowed="true" >
			</band>
		</columnFooter>
		<pageFooter>
			<band height="0"  isSplitAllowed="true" >
			</band>
		</pageFooter>
		<summary>
			<band height="33"  isSplitAllowed="true" >
				<textField isStretchWithOverflow="false" pattern="¤ #,##0.00" isBlankWhenNull="false" evaluationTime="Now" hyperlinkType="None"  hyperlinkTarget="Self" >
					<reportElement
						x="364"
						y="7"
						width="125"
						height="26"
						key="textField"/>
					<box></box>
					<textElement textAlignment="Right">
						<font size="14"/>
					</textElement>
				<textFieldExpression   class="java.lang.Integer"><![CDATA[$V{totalAmount}]]></textFieldExpression>
				</textField>
				<staticText>
					<reportElement
						x="492"
						y="9"
						width="26"
						height="14"
						key="staticText-5"/>
					<box></box>
					<textElement>
						<font size="8"/>
					</textElement>
				<text><![CDATA[USD]]></text>
				</staticText>
				<staticText>
					<reportElement
						x="15"
						y="7"
						width="112"
						height="26"
						key="staticText-6"/>
					<box></box>
					<textElement>
						<font size="14" isBold="true"/>
					</textElement>
				<text><![CDATA[TOTAL]]></text>
				</staticText>
			</band>
		</summary>
</jasperReport>

Como veran, se definen tres campos para los productos: name, quantity y amount, luego estos campos son desplegados en el área de detalle del reporte.

Ademas tambien estamos declarando una variable llamada totalAmount, que nos sirve calcular el total de la factura.

(invoice.jrxml)

<?xml version="1.0" encoding="UTF-8"  ?>
<!-- Created with iReport - A designer for JasperReports -->
<!DOCTYPE jasperReport PUBLIC "//JasperReports//DTD Report Design//EN" "http://jasperreports.sourceforge.net/dtds/jasperreport.dtd">
<jasperReport name="invoice">
	<property name="ireport.scriptlethandling" value="0" />
	<property name="ireport.encoding" value="UTF-8" />
 
	<parameter name="detailPath" isForPrompting="false" class="java.lang.String"/>
 
	<field name="clientName" class="java.lang.String">
		<fieldDescription><![CDATA[clientName]]></fieldDescription>
	</field>
	<field name="clientId" class="java.lang.String">
		<fieldDescription><![CDATA[clientId]]></fieldDescription>
	</field>
	<field name="invoiceNumber" class="java.lang.String">
		<fieldDescription><![CDATA[invoiceNumber]]></fieldDescription>
	</field>
	<field name="invoiceDate" class="java.lang.String">
		<fieldDescription><![CDATA[invoiceDate]]></fieldDescription>
	</field>
 
		<background>
			<band height="0"  isSplitAllowed="true" >
			</band>
		</background>
		<title>
			<band height="0"  isSplitAllowed="true" >
			</band>
		</title>
		<pageHeader>
			<band height="50"  isSplitAllowed="true" >
				<staticText>
					<reportElement
						x="5"
						y="6"
						width="227"
						height="35"
						key="staticText-2"/>
					<box></box>
					<textElement>
						<font fontName="FreeSerif" size="24"/>
					</textElement>
				<text><![CDATA[SomeCompany co.]]></text>
				</staticText>
			</band>
		</pageHeader>
		<columnHeader>
			<band height="0"  isSplitAllowed="true" >
			</band>
		</columnHeader>
		<detail>
			<band height="136"  isSplitAllowed="true" >
				<staticText>
					<reportElement
						x="460"
						y="43"
						width="0"
						height="0"
						key="staticText-1"/>
					<box></box>
					<textElement>
						<font/>
					</textElement>
				<text><![CDATA[Static Text]]></text>
				</staticText>
				<textField isStretchWithOverflow="false" isBlankWhenNull="false" evaluationTime="Now" hyperlinkType="None"  hyperlinkTarget="Self" >
					<reportElement
						x="95"
						y="30"
						width="173"
						height="18"
						key="textField"/>
					<box></box>
					<textElement>
						<font/>
					</textElement>
				<textFieldExpression   class="java.lang.String"><![CDATA[$F{clientName}+ "  - " + $F{clientId}]]></textFieldExpression>
				</textField>
				<textField isStretchWithOverflow="false" isBlankWhenNull="false" evaluationTime="Now" hyperlinkType="None"  hyperlinkTarget="Self" >
					<reportElement
						x="94"
						y="7"
						width="100"
						height="18"
						key="textField"/>
					<box></box>
					<textElement>
						<font/>
					</textElement>
				<textFieldExpression   class="java.lang.String"><![CDATA[$F{invoiceNumber}]]></textFieldExpression>
				</textField>
				<staticText>
					<reportElement
						x="4"
						y="30"
						width="26"
						height="18"
						key="staticText-3"/>
					<box></box>
					<textElement>
						<font/>
					</textElement>
				<text><![CDATA[To:]]></text>
				</staticText>
				<staticText>
					<reportElement
						x="4"
						y="7"
						width="81"
						height="18"
						key="staticText-4"/>
					<box></box>
					<textElement>
						<font/>
					</textElement>
				<text><![CDATA[Invoice Number:]]></text>
				</staticText>
				<staticText>
					<reportElement
						x="5"
						y="53"
						width="82"
						height="18"
						key="staticText-5"/>
					<box></box>
					<textElement>
						<font/>
					</textElement>
				<text><![CDATA[Date:]]></text>
				</staticText>
				<textField isStretchWithOverflow="false" isBlankWhenNull="false" evaluationTime="Now" hyperlinkType="None"  hyperlinkTarget="Self" >
					<reportElement
						x="96"
						y="53"
						width="78"
						height="18"
						key="textField"/>
					<box></box>
					<textElement>
						<font/>
					</textElement>
				<textFieldExpression   class="java.lang.String"><![CDATA[$F{invoiceDate}]]></textFieldExpression>
				</textField>
				<subreport  isUsingCache="true">
					<reportElement
						x="8"
						y="90"
						width="521"
						height="29"
						key="subreport-1"/>
					<dataSourceExpression><![CDATA[((net.sf.jasperreports.engine.data.JRXmlDataSource)$P{REPORT_DATA_SOURCE}).subDataSource($P{detailPath})]]></dataSourceExpression>
                    <subreportExpression  class="java.lang.String"><![CDATA["./invoice-detail.jasper"]]></subreportExpression>
				</subreport>
			</band>
		</detail>
		<columnFooter>
			<band height="0"  isSplitAllowed="true" >
			</band>
		</columnFooter>
		<pageFooter>
			<band height="0"  isSplitAllowed="true" >
			</band>
		</pageFooter>
		<summary>
			<band height="0"  isSplitAllowed="true" >
			</band>
		</summary>
</jasperReport>

Acá es donde se pone un poco confuso :) Donde tenemos que poner nuestra atención es en el elemento subreport. Este elemento también puede ser creado usando el iReport.

reportElement, define la posición donde se encontrara el subreporte.

dataSourceExpression, en la expresion estamos indicando que vamos a usar el un sub data source, del data source principal del reporte.
“detailPath”, es una xpath que indicara la fuente de datos del subreporte.

subreportExpression, contiene la localización del diseño compilado del reporte de detalle, en consecuencia este es el path de un archivo .jasper.

Java

package bo.sumasoftware.hellojasperreports;
 
import net.sf.jasperreports.engine.*;
import net.sf.jasperreports.engine.util.JRLoader;
import net.sf.jasperreports.engine.data.JRXmlDataSource;
 
import java.util.HashMap;
 
/**
 * @author renan
 */
public class WriteInvoiceBasic {
    public static void main(String[] args) throws JRException {
        JasperCompileManager.
                compileReportToFile( "src/main/jrxml/invoice.jrxml","invoice.jasper");
        JasperCompileManager.
                compileReportToFile( "src/main/jrxml/invoice-detail.jrxml","invoice-detail.jasper");
 
        JasperReport master = (JasperReport)JRLoader.loadObject("invoice.jasper");
        JRXmlDataSource xmlDataSource = new JRXmlDataSource("src/main/xml/invoice.xml", "/invoice");
        HashMap hashMap = new HashMap();
        hashMap.put("detailPath","/invoice/products/product");
        JasperPrint jasperPrint = JasperFillManager.fillReport(master, hashMap, xmlDataSource);
        JasperExportManager.exportReportToPdfFile(jasperPrint, "invoice-basic.pdf");
    }
}

Compilación de los reportes. Como veran lo primero que hacemos es compilar los reportes maestro y detalle. al compilar estamos creando los respectivos archivos .jasper de cada reporte.
Hacemos esto, ya que en el reporte maestro se necesita pasar un archivo .jasper.

Cargando reporte maestro. Para realizar esto estamos usando la clase JRLoader y su método loadObject para leer el reporte maestro cmpilado invoice.jasper.

Creacion de JRXMLDataSource. Al crear este objeto, le pasamos como parámetro el archivo xml de datos y también una expresión xpath que indica el nodo raiz de datos para el reporte principal.

Definición de parámetros. En un HashMap estamos definiendo un parámetro llamado “detailPath”. detailPath indica contiene una expresión xpath que indica el data source del subreporte.
Esta es la parte importe. Si nos equivocamos en definir este parámetro el subreporte simplemente no mostrar información.
También tenemos que hacer notar que este es un parámetro definido en el diseño del reporte maestro y se hace referencia a este en el elemento dataSourceExpression.

Impresión del reporte. Acá ya solo se llena el reporte y luego se lo imprime en un archivo pdf.

:) bueno, hasta aquí por hoy. :)
pueden bajar el código fuente. Este es un poco diferente pero tiene dos ejemplos, uno básico y otro mas completo.

Renan Huanca JasperReports ,