jueves, 22 de enero de 2009

Invertir los Ejes en una Grafica de jfreechart

Bien esta semana he tenido que actualizar un par de gráficas dentro de un reporte, para esto las gráficas se generan con jfreechart que es una librería para hacer dicha tarea de manera mas fácil y obteniendo resultados muy buenos.

Las gráficas que se estaban generando tenían un pequeño detalle y es que la gráfica debería de contener los valores negativos de las y en la parte superior y no en la parte inferior que es como esta por default y es por eso que revisando ejemplos, asi como el api de jfreechart pues encontré la forma de hacerlo y se puede hacer tanto para el eje x como para el eje y.

por ejemplo tenemos la siguiente grafica con dos series de valores, uno corresponde a la funcion
y = x, y el segundo corresponde a la serie de valores y = x + 2

Bien para esto tengo el siguiente código:

import java.awt.Color;
import java.awt.image.BufferedImage;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.io.File;
import java.io.*;
import org.jfree.chart.ChartFactory;
import org.jfree.chart.ChartUtilities;
import org.jfree.chart.JFreeChart;
import org.jfree.chart.axis.AxisLocation;
import org.jfree.chart.axis.NumberAxis;
import org.jfree.chart.plot.PlotOrientation;
import org.jfree.chart.plot.XYPlot;
import org.jfree.chart.renderer.xy.StandardXYItemRenderer;
import org.jfree.data.xy.XYSeries;
import org.jfree.data.xy.XYSeriesCollection;

public class EjemploGrafica {

public BufferedImage generaGrafica(ArrayList areo, ArrayList oseo, String title) {
System.out.println(" Generando la grafica con titulo " + title);
BufferedImage buf = null;
try {

XYSeries series = this.llenaSerie(areo,"Serie Uno");
XYSeries series2 = this.llenaSerie(oseo,"Serie Dos");

XYSeriesCollection data = new XYSeriesCollection(series);
XYSeriesCollection data2 = new XYSeriesCollection(series2);
//Se crea el objeto para generar la grafica
JFreeChart chart = ChartFactory.createXYLineChart(
title,
"",
"",
null,
PlotOrientation.VERTICAL,
false,
true,
false
);

chart.setBorderVisible(true);
chart.setBorderPaint(Color.black);
XYPlot plot = chart.getXYPlot();
pintaSerieCirculo(plot,data );
pintaSerieCirculo(plot,data2 );

/*Comentar esta linea si únicamente queremos que retorne la BufferreImage y el catch con la IOException */
ChartUtilities.saveChartAsJPEG(new File("c:\\Barchart.jpg"), chart, 500,
300);

buf = chart.createBufferedImage(500,300);
} catch (IOException e) {
e.printStackTrace();
System.err.println("Error creando grafico.");
} catch (Exception e) {
System.out.println(e.toString());
System.err.println("Error creando grafico.");
}

return buf;
}


private void pintaSerie(XYPlot plot, XYSeriesCollection data){
int index = plot.getDatasetCount();

System.out.println(" numero de data sets " + index);
plot.setDataset(index,data);
System.out.println(" numero de data sets " + index);
StandardXYItemRenderer sxyiRender = new StandardXYItemRenderer();
//sxyiRender.setPlotImages(true);
plot.setRenderer(index,sxyiRender);
}

private void pintaSerieCirculo(XYPlot plot, XYSeriesCollection data){
int index = plot.getDatasetCount();

System.out.println(" numero de data sets " + index);
plot.setDataset(index,data);
System.out.println(" numero de data sets " + index);
StandardXYItemRenderer sxyiRender = new StandardXYItemRenderer();
//sxyiRender.setPlotImages(true);
sxyiRender.setShapesFilled(true);
sxyiRender.setBaseSeriesVisible(true);
sxyiRender.setBaseShapesVisible(true);
plot.setRenderer(index,sxyiRender);

}

private XYSeries llenaSerie(ArrayList data, String title) {
BeanValoresGrafica valores = null;
XYSeries series = new XYSeries(title);
for(Object valorXy : data){
valores = (BeanValoresGrafica) valorXy;
series.add(valores.getX(), valores.getY());
}
return series;
}

public static void main(String[] args) {
BeanValoresGrafica b = null;
ArrayList a = new ArrayList();
for(int i = -5 ; i < b =" new" ab =" new" i =" -2" b =" new">

Ahora yo necesito que mi gráfica quede asi :
Como observan los valores negativos de y se encuentran en la parte superior y no en la inferior para invertirlos realizaremos lo siguiente (incluir esta parte de codigo despues de obtener el objeto XYPlot y las llamadas del metodo pintaSerieCirculo)

.
.
pintaSerieCirculo(plot,data2 );
plot.setDomainAxisLocation(AxisLocation.TOP_OR_LEFT);
NumberAxis domainAxis = (NumberAxis) plot.getDomainAxis();
//*Invierte los valores del eje x */
// domainAxis.setInverted(true);
NumberAxis rangeAxis = (NumberAxis) plot.getRangeAxis();
//*Aqui es donde se invirte el eje y*/
rangeAxis.setInverted(true);
ChartUtilities.saveChartAsJPEG(new File("c:\\Barchart.jpg"), chart, 500,
300);



El metodo que genera la grafica nos retorna un objeto de tipo java.awt.image.BufferedImage este objeto podemos utilizarlo par mostrarlo en una aplicación swing o en un reporte de jasperreport o guardar la imagen en jpg y adjuntarla en algún informe, etc.

Bien pues es lo que yo necesitaba y espero que les sirva

La grafica final :

Como observan es lo mismo que lo anterior solo que se colocaron las etiquetas del eje x en la parte superior para eso tenemos el siguiente código:

AxisLocation axloc = plot.getDomainAxisLocation();
plot.setDomainAxisLocation(AxisLocation.TOP_OR_LEFT);


Bueno eso es todo, ha se me olvidaba que yo utilizo un bean para pasar valores le coloco el bean que no es la gran cosa pero es parte del codigo

import java.io.Serializable;

public class BeanValoresGrafica implements Serializable {


public BeanValoresGrafica() {
}

private double x;
private double y;

public double getX(){
return x;
}

public double getY(){
return y;
}

public double setX(double x){
return this.x = x;
}

public double setY(double y){
return this.y = y;
}

}

martes, 13 de enero de 2009

Acceder a un Ftp con jakarta commons-net

El proyecto jakarta commons-net nos proporciona implementaciones protocolos de Internet en java para poder utilizarlos en el lado del cliente. Los protocolos que soporta son los siguientes:
  • FTP/FTPS
  • NNTP
  • SMTP
  • POP3
  • Telnet
  • TFTP
  • Finger
  • Whois
  • rexec/rcmd/rlogin
  • Time (rdate) and Daytime
  • Echo
  • Discard
  • NTP/SNTP

En este ejemplo veremos como acceder a un ftp con esta libreria

Para usarlo tenemos que descargar los siguientes jar de la pagina oficial:

- commons-net-1.4.1.jar
- jakarta-oro-2.0.8.jar


El primer jar nos proporciona las clases que implementan los protocolos antes mencionados y en el segundo jar contiene algunas clases para evaluar expresiones. El primero usa clases del segundo por lo cual necesitamos agregar ambos a nuestro classpath.

Aquí tenemos el ejemplo :

import java.io.IOException;
import java.net.SocketException;
import org.apache.commons.net.ftp.FTPClient;
import org.apache.commons.net.ftp.FTPClientConfig;
import org.apache.commons.net.ftp.FTPFile;

public class Main {
public static void main(String[] args) {
FTPClient f = new FTPClient();
try {
FTPClientConfig conf = new FTPClientConfig(FTPClientConfig.SYST_UNIX); //Este objeto nos
f.configure(conf); //permite configurar opciones de conexion como idioma y sistema de archivos
f.connect("127.0.0.1"); // ip del servidor ftp
f.login("usuario", "usuario"); // usuario y password para conectarnos al ftp
f.changeWorkingDirectory("diruno"); // Cambiamos de la raiz al subdirectorio uno
System.out.println(" Crea directorio ? "+f.mkd("dirprueba")); //crea un directorio en diruno
FTPFile[] files = f.listFiles(); // Obtiene los archivos del servidor y los mostramos
System.out.println(f.isConnected());
for (FTPFile arch : files){
System.out.println(arch.toString());
}
f.disconnect();
System.out.println(f.isConnected());
} catch (IOException ex) {
ex.printStackTrace();
}
}
}

Les dejo el link de la pagina oficial http://commons.apache.org/net/


Upate: Les dejo un ejemplo mas, es como el anterior pero almacena un arcivo de la maquina local en el ftp



public class Main {

 public static void main(String[] args) {
  FTPClient f = new FTPClient();
  try {
  FTPClientConfig conf = new FTPClientConfig(FTPClientConfig.SYST_UNIX); //Este objeto nos
  f.configure(conf); //permite configurar opciones de conexion como idioma y sistema de archivos
  f.connect("127.0.0.1"); // ip del servidor ftp
  f.login("usuario", "usuario"); // usuario y password para conectarnos al ftp
  System.out.println(f.isConnected());
  f.changeWorkingDirectory("diruno"); // Cambiamos de la raiz al subdirectorio uno
  System.out.println(" Crea directorio ? "+f.mkd("dirprueba")); //crea un directorio en diruno
 
  FileInputStream fis = new FileInputStream("archivo.doc"); //Se abre un archivo de nuestra maquina local
  f.setFileType(f.BINARY_FILE_TYPE); //Se pone tipo binario para poder enviar archivos de cualquier tipo
  boolean res = ftpClient.storeFile("/diruno/dirprueba", fis ); //Con esta instruccion se sube el archivo al ftp
  System.out.println("Resultado de subir el archivo es " + res);
 
  FTPFile[] files = f.listFiles(); // Obtiene los archivos del servidor y los mostramos
  for (FTPFile arch : files){
  System.out.println(arch.toString());
  }
 
 
  f.disconnect();
  System.out.println(f.isConnected());
  } catch (IOException ex) {
  ex.printStackTrace();
  }
 }
}

jueves, 8 de enero de 2009

Usar el protocolo samba con jCIFS

En el proyecto donde estoy colaborando hay una aplicación que necesita escribir archivos en un directorio compartido en un servidor windows por lo que necesitamos usar el protocolo CIFS/SMB, bien para esto tenemos la librería jCIFS que es una implementación de dicho protocolo y esta hecha en java completamente además de que es opensource.

También es posible usar esta librería para compartir recursos entre maquinas windows y máquinas unix que cuenten con el servicio samba.

Por ejemplo en este metodo escribimos un archivo en la carpeta compartida por otra maquina:

private boolean escribeArchivo(String encodedMessage, String nombreArchivo)
throws SmbException, MalformedURLException, UnknownHostException, IOException{

boolean exitoArchivo = false;

//String url = "smb://127.0.0.1/compartida/"+ nombreArchivo ;
//String url = "smb://usuario:usuario@127.0.0.1/compartida/"+ nombreArchivo ;
String url = "smb://"+ USR_SERVIDOR +":"+ PASS_SERVIDOR +"@"
+ URL_SERVIDOR + nombreArchivo + EXT_ARCHIVO;

try{
SmbFileOutputStream out = new SmbFileOutputStream(url, false);

out.write(encodedMessage.getBytes());
// encodeMessage es el texto que contiene el archivo
// aqui podemos enviar los bytes de algun archivo de la maquina local

out.close();

exitoArchivo = true;

System.out.println("generado " + url );
} catch(IOException ex){
exitoArchivo = false;
} finally{
return exitoArchivo;
}
}


Para borrar un archivo en la carpeta compartida:

private void borraArchivo(String archivo) throws SmbException,
MalformedURLException, UnknownHostException{

//String url = "smb://127.0.0.1/compartida/"+ nombreArchivo ;
//String url = "smb://usuario:usuario@127.0.0.1/compartida/"+ nombreArchivo ;
String url = "smb://"+ USR_SERVIDOR +":"+ PASS_SERVIDOR +"@"+ URL_SERVIDOR ;
String rutArchivo = url + archivo;
SmbFile sFile = new SmbFile(rutArchivo);
if(sFile.exists())
sFile.delete();
}



Para descargar la libreria y un poco de mas informacion pues sigan este link
http://jcifs.samba.org/

lunes, 24 de noviembre de 2008

Campos BLOB

En los post anteriores sobre insertar imágenes en una base de datos mediante una aplicación web o una stand alone mencionamos el tipo de dato BLOB, donde se almacena información en formato binario, este tipo de dato puede variar, varia de acuerdo a las bases de datos , y como lo apunta Danguer en su comentario podría darnos problemas si el archivo es mas grande de lo que nos permite guardar el tipo BLOB. Entonces hay que revisar si el motor de base de datos que estamos usando y su implementación de los BLOB estan de acuerdo a nuestras necesidades en otro caso seria mejor buscar otro tipo de dato como lo hizo Danguer que uso un tipo LONGBLOB

Bien les dejo una tablita tipos de datos BLOB de MySQL que muestra la capacidad de almacenamiento:

TINYBLOB, TINYTEXT L+1 byte, donde L <>
BLOB, TEXT L+2 bytes, donde L <>
MEDIUMBLOB, MEDIUMTEXT L+3 bytes, donde L <>
LONGBLOB, LONGTEXT L+4 bytes, donde L <>


En derby los datos BLOB se les puede asignar un tamaño, por default el tamaño es de 2 gb.


Mas informacion en:

http://dev.mysql.com/doc/refman/5.0/es/storage-requirements.html
http://db.apache.org/derby/docs/10.4/ref/ref-single.html

jueves, 20 de noviembre de 2008

OAS + JAAS

Hace unos días, tuve que usar el estándar de
seguridad Java (JAAS) para mayor referencia Click Aquí.
En esta ocasión para el servidor de aplicaciones
OAS.
En esta página puedes revisar a fondo
JAAS sobre OAS.Jaas sobre OAS

En esta ocasión solo definiré perfiles y usuarios
el archivo web.xml y su correspondiente en el archivo
jazn-data.xml por parte de OAS.


Los archivos que deben ser modificados para poder
implementar esta seguridad son los siguientes:

web.xml




Continua...

miércoles, 19 de noviembre de 2008

Insertar una imagen en una base de datos mediante una aplicacion stand alone

En la entrada anterior vimos como insertar una imagen en la base de datos en una app web, bueno el procedimiento anterior es aplicable a cualquier otro archivo ya que en donde se inserta es un dato de tipo BLOB es decir un archivo muy grande (bueno creo que es hasta 4gb) en modo binario, ahora veremos como hacerlo desde la aplicación stand alone o de escritorio (Esto lo pidieron en un comentario jejeje).

El proyecto lo hice en netbeans, Lo que necesitamos:

- Driver para la base de datos, (en mi caso es derbyclient.jar)
- Base de datos con soporte para datos BLOB
- Netbeans (opcional)

Tenemos la siguiente tabla (la definición corresponde a derby tal vez necesite adecuarse para MySql y/u otras) :

create table IMAGEN_T
(
ID_IMAGEN INTEGER not null primary key,
DESCRIPCION VARCHAR(100),
IMAGEN BLOB(1048576)
)

Para insertar las imágenes tenemos un DAO el cual contiene el método insertaImagen (aunque este método debe funcionar para cualquier archivo recordemos que el archivo se guarda en binario)

insertaImagen(String nameFile, int id)
throws FileNotFoundException, SQLException{

File fileIn = new File(nameFile);
InputStream fis = new FileInputStream(fileIn);
ps = conn.prepareStatement("INSERT INTO IMAGEN_T VALUES (?, ?, ?)");
ps.setInt(1,id);
ps.setString(2, "Probando insertar una imagen");
int fileLength = (int) fileIn.length();
System.out.println(" los datos " + fileLength + " fis " + fis.toString());
ps.setBinaryStream(3, fis, fileLength);
ps.executeUpdate();
ps.close();

}

En este método creamos un File con el nombre del archivo que recibe (el nombre contiene la ruta completa) para a su vez crear un FileInputStream que a su vez asignamos a un InputStream, con estos objetos se leerán los bytes del archivo, obtenemos un objeto PreparedStatment y colocamos el id para el registro, una descripción (aqui podria ser mejor guardar el nombre para cuando se necesite recuperar el archivo recuerden que esta app es solo un ejemplo) y posteriormente se realiza el setBinaryStream y le pasamos el objeto InputStream para que pueda leer los bytes y también le pasamos el tamaño del archivo es decir el numero de bytes que se tienen que leer.

A continuación tenemos el método que recupera el archivo:

recuperaImagenBD(int idImagen, String path)
throws IOException, SQLException{

FileOutputStream fos = null;
Connection conn=null;
PreparedStatement ps=null;
ResultSet rs = null;
Statement st = null;
String sql = "SELECT IMAGEN FROM IMAGEN_T WHERE ID_IMAGEN = ?";
ps = conn.prepareStatement(sql);
ps.setInt(1, idImagen);

rs = ps.executeQuery();
if (rs.next()){

String pathname= path;
File file = new File(pathname);
fos = new FileOutputStream(file);
Blob bin = rs.getBlob("IMAGEN");
InputStream inStream = bin.getBinaryStream();
int size = (int)bin.length();
byte[] buffer = new byte[size];
int length = -1;
while ((length = inStream.read(buffer)) != -1) {
fos.write(buffer, 0, length);
}
}

}

En este método tenemos que crear un objeto FileOutputStream para poder escribir los bytes que nos retorna la consulta, a este objeto le pasamos un objeto file que ha sido creado con una ruta donde se guardara el archivo, después obtenemos el dato BLOB y de este obtenemos un objeto InputStream para leer los bytes, después obtenemos el numero de bytes del Blob, posteriormente creamos un arreglo de bytes en el que se leerán los bytes y de donde el outputStream obtendrá los bytes, le hice una pequeña ventanita para hacer pruebitas



En cuanto pueda colocare los proyectos en algun servicio de hostig, si alguien le intereas el codigo escriba un comentario con su mail para enviarselos.
Tal vez haya algunas mejoras en el código, espero sus comentarios ...

lunes, 17 de noviembre de 2008

Insertar imagenes en una base de datos en una aplicacion web

Que tal, en esta primer entrada veremos como insertar una imagen en la base de datos y también como recuperarla y mostrarla dentro de nuestra aplicación web. Para hacer esto, haremos uso de un par de jar's de jakarta-commons, no hay que re-inventar la rueda.

Lo que necesitamos:

- eclipse (con wtp para mayor comodidad)
- apache tomcat 6 (o algun otro contenedor de servlets)
- commons-fileupload-1.2.jar
- commons-io-1.3.1.jar
- mysql-connector-java-5.1.5-bin.jar (Este driver depende de su motor de base de datos)
- MySql 5.0.67 (Esta es la bd que uso, podrían ocupar cualquier otra que soporte datos BLOB)
- Opcionalmente: log4-1.2.11.jar, jstl.jar, standar.jar (las ultimas dos vienen en los ejemplos de apache-tomcat 6, en versiones anteriores se encuentran en el directorio lib de tomcat)

No es absolutamente necesario usar eclipse, podrían realizar el proyecto con algún otro ide o sin usar algún ide.

Para insertar la imagen realice el siguiente método que pertenece a mi DAO:

public void insertaImagenProducto(int idProducto,
InputStream inps, long size) {

PreparedStatement ps=null;
try {

ps = con.prepareStatement(
"UPDATE PRODUCTOS SET IMAGEN = ? WHERE" +
" PRODUCTO_ID = ?");

ps.setBinaryStream(1, inps, (int)size);
ps.setInt(2, idProducto);
ps.executeUpdate();
ps.close();

} catch (SQLException e) {

e.printStackTrace();
}
}


En el método de insertaImagen, únicamente recibo un InputStream del cual se leerán los bytes que se insertaran en el campo BLOB, tambien se recibe el tamaño del InputStream o el numero de bytes que contiene y finalmente se llama al método setBinaryStream del objeto preparedStatment con el cual se inserta la imagen en la bd

Para recuperar un dato BLOB de la bd se realiza lo siguiente:
public byte[] obtenImagenProducto(int idProducto)  {

ResultSet rst = null;
PreparedStatement pstm = null;
byte[] buffer = null;

try {
logger.info("Datos producto id " +idProducto);
String sql = "select imagen from
productos where producto_id = ?";
pstm = con.prepareStatement(sql);
pstm.setInt(1, idProducto);
rst = pstm.executeQuery();
while (rst.next()){
Blob bin = rst.getBlob("imagen");
if (bin != null) {
InputStream inStream = bin.getBinaryStream();
int size = (int) bin.length();
System.out.println(" El tamaño en bytes " + size);
buffer = new byte[size];
int length = -1;
int k = 0;
try {
inStream.read(buffer, 0, size);
} catch (IOException ex) {
ex.printStackTrace();
}
}
}

} catch (SQLException ex) {
logger.error("ERROR " + ex);
return null;
} finally {
/*
rst.close();
stm.close();
*/
rst = null;
pstm = null;
}
return buffer;
}
Este método obtiene un dato de tipo BLOB, si el dato es diferente de nulo entonces se crea un objeto de tipo InputStream con el cual se leerán los bytes del dato blob, se crea un arreglo de bytes de acuerdo al tamaño del blob y posteriormente se leen, una vez leídos los bytes estos simplemente se retornan en el arreglo creado, en la siguiente capa se reciben estos bytes y se envian al navegador.

Lo anterior es la parte que pertenece al modelo, ahora vamos con la parte correspondiente a la vista, en esta parte tenemos un jsp que contiene el siguiente formulario :

<form name="myform" action="./ServletProductoImagen"
method="post" enctype="multipart/form-data">

<input type="hidden" value="${param.idProducto}" name="idProducto">
Selecciona la Image:

<input type="file" name="myimage">

<input type="submit" name="Aceptar" value="Submit your files">
<form>
Bien con este formulario escogeremos el archivo que se agregara a la base de datos,
yo le paso un parámetro, el idProducto con este sabre en que registro insertar la imagen,

Ahora veamos el servlet que inserta la imagen, en el método post :
// first check if the upload request
//coming in is a multipart request
//Revisa si la peticion es multipart
boolean isMultipart = ServletFileUpload.isMultipartContent(request);

// Create a factory for disk-based file items
//Esto es parte de la lib de commons-fileupload
//y es un objeto para generar archivos temporales
FileItemFactory factory = new DiskFileItemFactory();

// Create a new file upload handler
//Aqui crea un objeto para manejar la peticion
//que llega con un archivo
ServletFileUpload upload = new ServletFileUpload(factory);


// parse this request by the handler
// this gives us a list of items from the request
List items = null;
try {
//Se obtienen los items de la forma
//es decir obtenemos los parametros de la forma
items = upload.parseRequest(request);
} catch (FileUploadException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
String idProducto = "";
Iterator itr = items.iterator();
while(itr.hasNext()) {

//recorremos los items en busca del id
//para realizar el insert
FileItem item = (FileItem) itr.next();

if(item.isFormField()) {
// get the name of the field
String fieldName = item.getFieldName();

if(fieldName.equals("idProducto"))
idProducto = item.getString();
}
logger.info("ID Producto" + idProducto);
}
itr = items.iterator();
//ahora lo recorremos para obtener el archivo que se
//envio en la forma
while(itr.hasNext()) {
FileItem item = (FileItem) itr.next();

// check if the current item is a form field or
//an uploaded file
if(! item.isFormField() ){

// the item must be an uploaded file save it to disk.
// Note that there
// seems to be a bug in item.getName() as it
//returns the full path on
// the client's machine for the uploaded file name,
// instead of the file
// name only. To overcome that, I have used a
// workaround using
// fullFile.getName().
//Aqui es donde se obtiene el nombre del archivo, esto podriamos
//usarlo si queremos gurdar el nombre o guardar el archivo en
//alguno de nuestros directorios.
//File fullFile = new File(item.getName());
//File savedFile = new File(fullFile.getName());
try {
//Este metodo comentado escribe el archivo en nuestro
//sistema de archivos con una ruta adecuada
//item.write(savedFile);

//pero lo que nos interesa es gurdar la imagen en la bd, asi
//que invocamos a nuestro dao y le pasmos los valores
//necesarios y es todo
daoProductos.insertaImagenProducto(
Integer.parseInt(idProducto),
item.getInputStream(),
item.getSize());
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}

System.out.println("Archivo guardado");
}
}

RequestDispatcher r =
request.getRequestDispatcher("./index.jsp");

r.forward(request, response);
}
Aqui es donde hacemos uso de el jar commons-fileupload, con este obtenemos
el archivo que se envio al servlet a travez de la forma, revisamos por los
parametros que se encuentran en la forma, el id para saber el registro en
donde se insertara la imagen, posteriormente obtenemos un inputStream con los
bytes de la imagen y el numero de bytes. Y lo enviamos a nuestro dao para que
realize el insert en la bd.

Para terminar, para mostrar la imagen en nuestro jsp entonces invocamos al metodo
doGet de el servlet en el cual tenemos lo siguiente:
String idProducto = request.getParameter("idProducto");
System.out.println(" El id del idProducto " + idProducto);
if(idProducto!=null && !idProducto.equals("")){

int idProd = Integer.parseInt(idProducto);
response.setContentType("image/gif");
byte [] imag = this.obtieneProducto(idProd);
if(imag != null) {
ServletOutputStream out = response.getOutputStream();
out.write(imag);
}
}
Aqui le enviamos el id del registro del cual se obtendra la imagen despues colocamos el contentype del response como image, invocamos anuestro dao que nos devolvera los bytes, obtenemos el ServletOutputStream para enviar los bytes de la imagen, en nuestro jsp simplemente hariamos:
<img src="./ServletProductoImagen?idProducto=${producto.idProducto}"
alt="${producto.nombre}" height="150" width="150" >
Espero colocar el proyecto de eclipse para que puedan descargarlo solo debo ver como o donde