Salve a tutti, spero di aver scelto la sezione corretta per farvi questa domanda.
Ho un problema con un web service che legge alcune informazioni da un file xml e le stampa. Vi mostro il codice e alla fine vi spiego quale penso sia il problema, nella speranza che qualcuno mi aiuti a comprendere cosa sto sbagliando.
Questo è un frammento del file xml (per farvi comprendere la maniera in cui è strutturato:
codice:
<?xml version="1.0" encoding="UTF-8"?>
<prodotti>
<prodotto id="01">
<nome>Navel</nome>
<categoria>Arance</categoria>
<pezzatura>
<confezione tipo = "cassa" peso = "15" prezzo= "15"/>
<confezione tipo = "sacchetto" peso = "3" prezzo="6"/>
<confezione tipo = "plateau" peso = "10" prezzo="12"/>
</pezzatura>
</prodotto>
<prodotto id="03">
<nome>Limoni_di_Sorrento</nome>
<categoria>Limoni</categoria>
<pezzatura>
<confezione tipo = "sacchetto" peso = "3" prezzo="7.50"/>
<confezione tipo = "plateau" peso = "7" prezzo="14"/>
</pezzatura>
</prodotto>
</prodotti>
Per prima cosa ho creato due bean per gestire il tipo di oggetti che dovranno essere estrapolati dal file xml.
Prodotto.java:
codice:
public class Prodotto {
private int id;
private String nome;
private String categoria;
private Confezione[]
confezioni;
public int getID() {
return id;
}
public void setID(int i) {
id = i;
}
public String getNome() {
return nome;
}
public void setNome(String n) {
nome = n;
}
public String getCategoria() {
return categoria;
}
public void setCategoria(String c) {
categoria = c;
}
public Confezione[] getConfezione() {
return confezioni;
}
public void setConfezioni(Confezione[] conf) {
confezioni = conf;
}
}
Confezione.java:
codice:
public class Confezione {
String tipo;
int peso;
float prezzo;
public String getTipo() {
return tipo;
}
public void setTipo(String t) {
tipo = t;
}
public int getPeso() {
return peso;
}
public void setPeso(int p) {
peso = p;
}
public float getPrezzo() {
return prezzo;
}
public void setPrezzo(float pr) {
prezzo = pr;
}
}
A questo punto ho creato una classe che eseguisse concretamente le operazioni:
codice:
public class ProdottoDB {
Prodotto[] prodotti;
Confezione[] confezioni;
public ProdottoDB(Document doc) throws Exception {
NodeList list = doc.getElementsByTagName("prodotto");
int length = list.getLength();
prodotti = new Prodotto[length];
Prodotto p = null;
for (int i = 0; i < length; i++) {
Element elem = (Element)list.item(i);
p = new Prodotto();
p.setID(Integer.parseInt(elem.getAttribute("id")));
p.setNome(getValue(elem, "nome"));
p.setCategoria(getValue(elem, "categoria"));
NodeList listConf = elem.getElementsByTagName("confezione");
confezioni = new Confezione[listConf.getLength()];
for (int j = 0; j < listConf.getLength(); j++) {
Element elemConf = (Element)listConf.item(j);
Confezione c = new Confezione();
c.setTipo(elemConf.getAttribute("tipo"));
c.setPrezzo(Float.parseFloat(elemConf.getAttribute("prezzo")));
c.setPeso(Integer.parseInt(elemConf.getAttribute("peso")));
confezioni[j] = c;
System.out.println("confezioni");
}
p.setConfezioni(confezioni);
prodotti[i] = p;
}
}
public Prodotto[] getProdotti() {
return prodotti;
}
public float getPrezzo(int id, String categoria) {
for (int i = 0; i < prodotti.length; i++) {
if (id == prodotti[i].getID()) {
Confezione[] c = prodotti[i].getConfezione();
for (int j=0; j<c.length; j++) {
if (categoria.equals(c[j].getTipo()))
return c[j].getPrezzo();
}
}
}
return -1;
}
/*
* Legge il valore di un nodo Element
*/
private String getValue(Element elem, String name) {
NodeList l = elem.getElementsByTagName(name);
if (l == null || l.getLength() == 0)
return null;
elem = (Element)l.item(0);
return elem.getFirstChild().getNodeValue();
}
}
Lato server il codice dovrebbe essere il seguente:
codice:
public class TerramicaService {
private static String file = "Terramica/ProdottiTerramica.xml";
public static Prodotto[] elenco() throws Exception {
MessageContext msgCtx = MessageContext.getCurrentMessageContext();
ServletContext ctx = (ServletContext) msgCtx.getProperty(HTTPConstants.MC_HTTP_SERVLETCONTEXT);
String rpath = ctx.getRealPath(file);
BufferedInputStream in = new BufferedInputStream(new FileInputStream(rpath));
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
factory.setNamespaceAware(true);
DocumentBuilder builder = factory.newDocumentBuilder();
Document doc = builder.parse(in);
ProdottoDB db = new ProdottoDB(doc);
Prodotto[] prod = db.getProdotti();
return prod;
}
public float prezzo(int id, String tipo) throws Exception {
MessageContext msgCtx = MessageContext.getCurrentMessageContext();
ServletContext ctx = (ServletContext) msgCtx.getProperty(HTTPConstants.MC_HTTP_SERVLETCONTEXT);
String rpath = ctx.getRealPath(file);
BufferedInputStream in = new BufferedInputStream(new FileInputStream(rpath));
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
factory.setNamespaceAware(true);
DocumentBuilder builder = factory.newDocumentBuilder();
Document doc = builder.parse(in);
ProdottoDB db = new ProdottoDB(doc);
float prezzo = db.getPrezzo(id, tipo);
return prezzo;
}
}
Mentre il client è questo:
codice:
public class TerramicaClient {
public static void main(String[] args) throws Exception {
BufferedReader console = new BufferedReader(new InputStreamReader(System.in));
System.out.println("Scegliere l'operazione da eseguire: ");
System.out.println("1 - Elenco prodotti: ");
System.out.println("2 - Ricerca prezzo: ");
int sel = Integer.parseInt(console.readLine());
//
//System.out.println("I prodotti non sono disponibili");
if (sel==1) {
ArrayList<Prodotto> prods = elenca();
for (Prodotto p : prods) {
System.out.println("ID: " + p.getID());
System.out.println("Categoria: " + p.getCategoria());
System.out.println("Nome: " + p.getNome());
Confezione[] confs = p.getConfezione();
for (int i=0; i<confs.length; i++) {
System.out.println("Tipo confezione: " + confs[i].getTipo());
System.out.println("Peso confezione: " + confs[i].getPeso());
System.out.println("Prezzo confezione: " + confs[i].getPrezzo());
}
}
}
if (sel==2) {
System.out.println("ID?: ");
int id = Integer.parseInt(console.readLine());
System.out.println("Tipo?: ");
String tipo = console.readLine();
float res = prezzo(id, tipo);
System.out.println("Prezzo: " + res);
}
}
private static ArrayList<Prodotto> elenca() throws Exception {
ArrayList<Prodotto> prs = new ArrayList<Prodotto>();
ServiceClient serviceClient = new ServiceClient();
OMFactory fac = OMAbstractFactory.getSOAP12Factory();
OMNamespace omNs = fac.createOMNamespace("http://www.terramica.it", "tns");
OMElement method = fac.createOMElement("elenco", omNs);
Options options = serviceClient.getOptions();
EndpointReference targetEPR = new EndpointReference("http://localhost:8081/axis2/services/TerramicaService");
options.setSoapVersionURI(Constants.URI_SOAP12_ENV);
options.setTo(targetEPR);
// invocazione del servizio utilizzando la MEP in-out
OMElement result = serviceClient.sendReceive(method);
// recupera il risultato
Iterator values = result.getChildrenWithName(new QName("http://service.terramica.it", "return"));
while (values.hasNext()) {
OMElement omElement = (OMElement) values.next();
Prodotto prod = (Prodotto) BeanUtil.deserialize(Prodotto.class, omElement, new DefaultObjectSupplier(), "prodotto");
prs.add(prod);
}
return prs;
}
private static float prezzo(int id, String categoria) throws Exception {
ServiceClient serviceClient = new ServiceClient();
OMFactory fac = OMAbstractFactory.getSOAP12Factory();
OMNamespace omNs = fac.createOMNamespace("http://service.terramica.it", "tns");
OMElement method = fac.createOMElement("prezzo", omNs);
OMElement arg0 = fac.createOMElement("id", omNs);
arg0.addChild(fac.createOMText(arg0, String.valueOf(id)));
method.addChild(arg0);
OMElement arg1 = fac.createOMElement("tipo", omNs);
arg1.addChild(fac.createOMText(arg1, categoria));
method.addChild(arg1);
Options options = serviceClient.getOptions();
EndpointReference targetEPR = new EndpointReference("http://localhost:8081/axis2/services/TerramicaService");
options.setSoapVersionURI(Constants.URI_SOAP12_ENV);
options.setTo(targetEPR);
// invocazione del servizio utilizzando la MEP in-out
OMElement result = serviceClient.sendReceive(method);
// recupera il risultato
float response = Float.parseFloat(result.getFirstElement().getText());
return response;
}
}
Purtroppo il risultato non è quello corretto anche se eclipse non segnala errori nel codice. Il messaggio che compare è il seguente:
codice:
ID: 1
Categoria: Arance
Nome: Navel
Exception in thread "main"
java.lang.NullPointerException
at it.terramica.client.TerramicaClient.main(TerramicaClient.java:46)
Facendo un po' di debug quello che mi sembra di capire è che per qualche motivo gli oggetti di tipo confezione non vengano salvati nella struttura dati corrispondente. Tramite TCPMon però ho verificato che il messaggio di risposta contiene tutti i dati necessari. A questo punto mi sono bloccato perchè non riesco a capire come risolvere la situazione... spero che qualcuno possa darmi una mano a capire dov'è l'errore!