webservice mit axis an mysql-db anbinden?

vase2k

Grünschnabel
Einen schönen guten Abend,

folgende Konstellation:
  • Webservice über POJO realisiert und als AAR-file deployed [code1]
  • Client als Konsolenanwendung realisiert [code2]
  • testweise den Client als Standalone-Anwendung realisiert, um zu testen, ob der DB-Zugriff funktioniert [code3]

code1
Code:
package de.axishotels;

import java.sql.*;

import com.mysql.jdbc.ResultSet;

public class HotelService {

	Hotel[] hotels;

	public HotelService() {	}

	public Hotel[] getHotels() {
		return hotels;
	}

	public Hotel[] findHotel(String hotelCode) {
			try {
				Class.forName("com.mysql.jdbc.Driver");
				Connection cn = DriverManager.getConnection(
						"jdbc:mysql://localhost:3306/travelagent", "root", "");
				String query = "SELECT * FROM hotels WHERE hotelcode LIKE '"
						+ hotelCode + "%'";
				// System.out.println(query);
				Statement stmt = cn.createStatement();
				java.sql.ResultSet result = stmt.executeQuery(query);
				int i = 0;
				while (result.next()) {
					hotels[i] = new Hotel(result.getString(2), result.getString(3),
							result.getString(4), Integer.parseInt(result
									.getString(5)), null);
					i++;
				}
			} catch (ClassNotFoundException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			} catch (SQLException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		
		
		return hotels;
	}
}

code2
Code:
package de.axishotels.client;

import javax.xml.namespace.QName;

import org.apache.axiom.om.OMElement;
import org.apache.axis2.AxisFault;
import org.apache.axis2.addressing.EndpointReference;
import org.apache.axis2.client.Options;
import org.apache.axis2.client.ServiceClient;
import org.apache.axis2.databinding.utils.BeanUtil;
import org.apache.axis2.engine.DefaultObjectSupplier;

import de.axishotels.Hotel;

public class AxisHotelsClient {

	@SuppressWarnings("unchecked")
	public static void main(String[] args1) throws AxisFault {

		ServiceClient sender = new ServiceClient();
		Options options = sender.getOptions();
		EndpointReference targetEPR = new EndpointReference(
				"http://localhost:8080/axis2/services/SimpleHotelService");
		options.setTo(targetEPR);

		// Die Operation "findHotel" soll aufgerufen werden
		QName opFindHotel = new QName("http://axishotels.de/xsd", "findHotel");

		// Die Parameter für die Operation "findHotel"
		// werden definiert...
		String hotelCode = "AX010";
		Object[] opArgs = new Object[] { hotelCode };

		// ...und ein AXIOM-OMElement mit der
		// Request-Nachricht erzeugt
		OMElement request = BeanUtil.getOMElement(opFindHotel, opArgs, null,
				false, null);

		// Der Request wird an den Service abgeschickt.
		// Der Aufruf erfolgt synchron mit dem
		// Kommunikationsmuster IN-OUT
		OMElement response = sender.sendReceive(request);
		
		// Diese Typen sollte der Web Service zurückliefern...
		Class[] returnTypes = new Class[] { Hotel.class };
		// Hotel[] returnTypes = new Hotel[100];
		// String returnTypes2 = new String();

		// ...und werden mit einer Hilfsroutine in ein
		// Objekt-Array überführt
		Object[] result = BeanUtil.deserialize(response, returnTypes,
				new DefaultObjectSupplier());
		

		System.out.println("Anzahl Objekte: " + result.length);
		for (int i = 0; i < result.length; i++) {
			Hotel hotel = (Hotel) result[i];
			if (hotel == null) {
				System.out.println("No entry for code: " + hotelCode);
				return;
			}

			System.out.println("Hotel Name: " + hotel.getHotelName());
			System.out.println("Hotel Code: " + hotel.getHotelCode());
			System.out.println("City: " + hotel.getCity());
			System.out.println("Stars: " + hotel.getNumberOfStars());

		}
	}
}

code3
Code:
package test;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.sql.Statement;
import de.axishotels.*;

public class dbTester {
	Hotel[] hotels = new Hotel[100];

	public void findHotels(String hotelCode) {
		try {
			Class.forName("com.mysql.jdbc.Driver");
			Connection cn = DriverManager.getConnection(
					"jdbc:mysql://localhost:3306/travelagent", "root", "");
			String query = "SELECT * FROM hotels WHERE hotelcode LIKE '"
					+ hotelCode + "%'";
			// System.out.println(query);
			Statement stmt = cn.createStatement();
			java.sql.ResultSet result = stmt.executeQuery(query);
			int i = 0;
			while (result.next()) {
				// System.out.println(result.getString(2) + "//"
				// + result.getString(3) + "//" + result.getString(4)
				// + "//" + result.getString(5));
				hotels[i] = new Hotel(result.getString(2), result.getString(3),
						result.getString(4), Integer.parseInt(result
								.getString(5)), null);
				i++;
			}
		} catch (ClassNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (SQLException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

	private void showHotels() {
		// TODO Auto-generated method stub
		for (int i = 0; i < hotels.length; i++) {
			if (hotels[i] != null) {
				System.out.println("Hotelname: " + hotels[i].getHotelName());
				System.out.println("Hotelcode: " + hotels[i].getHotelCode());
			}
		}
	}

	public static void main(String[] args) {
		dbTester runner = new dbTester();
		runner.findHotels("AX");
		runner.showHotels();
	}
}


gedacht war das ganze als dynamische version des ersten webservice aus dem buch Java Web Services mit Apache Axis2, wo die zu findenden Hotels direkt in dem POJO des Webservices implementiert waren.

doch nun zum eigentlichen problem: wenn ich den webservice deploye, und dann den client [code2] aufrufe, bekomme ich zwei exceptions:

exception1
Code:
Exception in thread "main" org.apache.axis2.AxisFault: Exception occurred while trying to invoke service method findHotel
	at org.apache.axis2.util.Utils.getInboundFaultFromMessageContext(Utils.java:486)
	at org.apache.axis2.description.OutInAxisOperationClient.handleResponse(OutInAxisOperation.java:343)
	at org.apache.axis2.description.OutInAxisOperationClient.send(OutInAxisOperation.java:389)
	at org.apache.axis2.description.OutInAxisOperationClient.executeImpl(OutInAxisOperation.java:211)
	at org.apache.axis2.client.OperationClient.execute(OperationClient.java:163)
	at org.apache.axis2.client.ServiceClient.sendReceive(ServiceClient.java:528)
	at org.apache.axis2.client.ServiceClient.sendReceive(ServiceClient.java:508)
	at de.axishotels.client.AxisHotelsClient.main(AxisHotelsClient.java:42)

das wäre dann diese zeile:
Code:
OMElement response = sender.sendReceive(request);

zweite exception
Code:
19:39:34,177 ERROR [RPCMessageReceiver] Exception occurred while trying to invoke service method findHotel
java.lang.reflect.InvocationTargetException
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
	at java.lang.reflect.Method.invoke(Method.java:597)
	at org.apache.axis2.rpc.receivers.RPCMessageReceiver.invokeBusinessLogic(RPCMessageReceiver.java:118)
	at org.apache.axis2.receivers.AbstractInOutSyncMessageReceiver.receive(AbstractInOutSyncMessageReceiver.java:39)
	at org.apache.axis2.engine.AxisEngine.receive(AxisEngine.java:497)
	at org.apache.axis2.transport.http.HTTPTransportUtils.processHTTPPostRequest(HTTPTransportUtils.java:328)
	at org.apache.axis2.transport.http.AxisServlet.doPost(AxisServlet.java:254)
	at javax.servlet.http.HttpServlet.service(HttpServlet.java:710)
	at javax.servlet.http.HttpServlet.service(HttpServlet.java:803)
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:290)
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
	at org.jboss.web.tomcat.filters.ReplyHeaderFilter.doFilter(ReplyHeaderFilter.java:96)
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
	at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:230)
	at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:175)
	at org.jboss.web.tomcat.security.SecurityAssociationValve.invoke(SecurityAssociationValve.java:179)
	at org.jboss.web.tomcat.security.JaccContextValve.invoke(JaccContextValve.java:84)
	at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:128)
	at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:104)
	at org.jboss.web.tomcat.service.jca.CachedConnectionValve.invoke(CachedConnectionValve.java:156)
	at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109)
	at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:241)
	at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:844)
	at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:580)
	at org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:447)
	at java.lang.Thread.run(Thread.java:619)
Caused by: java.lang.NullPointerException
	at de.axishotels.HotelService.findHotel(HotelService.java:53)
	... 29 more

irgendwie bin ich mittlerweile ein wenig am verzweifeln .. vielleicht hat jemand von euch ja nen hinweis für mich.

mfg && danke im voraus

vase2k :):)
 
Ich muss das Thema nochmal hoch holen .. ich hab mir jetzt eine Art Transportklasse gebaut, in der ich den Vektor, in dem die Objekte stehen, zurück an den Client sende. die Transportklasse an und für sich ist nix wildes:
Code:
package de.testService;

import java.util.Vector;

public class TransportContainer {

	public TransportContainer() {

	}

	public Vector v;

	public void setData(Vector data) {
		this.v = data;
	}

	public Vector getData() {
		return this.v;
	}
}

der Webservice sieht jetzt wie folgt aus:
Code:
package de.testService;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.util.Vector;

public class TestService {

	public Connection con = null;
	TransportContainer tc = new TransportContainer();
	Vector<Hotel> v = new Vector<Hotel>();

	public final void connection() throws Exception {
		Class.forName("com.mysql.jdbc.Driver");
		con = DriverManager.getConnection(
				"jdbc:mysql://localhost:3306/travelagent", "root", "");
	}

	public TransportContainer getHotels(String table) {
		try {
			connection();
			String sql = "SELECT * FROM " + table;
			PreparedStatement pStmt = con.prepareStatement(sql);
			ResultSet rs = pStmt.executeQuery();
			while (rs.next()) {
				v.addElement(new Hotel(rs.getString(2), rs.getString(3), rs
						.getString(4), rs.getString(6), rs.getInt(5)));
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
		tc.setData(v);
		return tc;

	}

}

und der passende Client dazu:
Code:
package de.wsTester;

import javax.xml.namespace.QName;

import org.apache.axis2.AxisFault;
import org.apache.axis2.addressing.EndpointReference;
import org.apache.axis2.client.Options;
import org.apache.axis2.rpc.client.RPCServiceClient;

import de.testService.*;

public class TestClient {

	public static void main(String[] args) throws AxisFault {
		
		RPCServiceClient sender = new RPCServiceClient();
		Options options = sender.getOptions();

		EndpointReference targetERP = new EndpointReference(
				"http://localhost:8080/axis2/services/testService");
		options.setTo(targetERP);

		QName opGetHotels = new QName("http://testService.de", "getHotels");

		String table = "hotels";
		Object[] opArgs = new Object[] { table };

		Class[] returnTypes = new Class[] { TransportContainer.class };
		Object[] response = sender.invokeBlocking(opGetHotels, opArgs,
				returnTypes);
	}

}

der Webservice arbeitet ordentlich, liefert laut soap-monitor auch das gewünschte Ergebnis zurück:
Code:
<?xml version='1.0' encoding='utf-8'?>
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
  <soapenv:Body>
    <ns:getHotelsResponse xmlns:ns="http://testService.de">
      <ns:return xmlns:ax22="http://testService.de/xsd" type="de.testService.TransportContainer">
        <ax22:data type="de.testService.Hotel">
          <ax22:hotelCity>München</ax22:hotelCity>
          <ax22:hotelCode>AX001</ax22:hotelCode>
          <ax22:hotelName>Axis2 Grand Hotel</ax22:hotelName>
          <ax22:numOfStars>5</ax22:numOfStars>
        </ax22:data>
      </ns:return>
    </ns:getHotelsResponse>
  </soapenv:Body>
</soapenv:Envelope>

also genau das, was ich haben will.

doch wenn ich den Client ganz normal aus eclipse starte, bekomme ich folgende Exception:
Code:
Exception in thread "main" java.lang.IllegalArgumentException: argument type mismatch
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
	at java.lang.reflect.Method.invoke(Unknown Source)
	at org.apache.axis2.databinding.utils.BeanUtil.deserialize(BeanUtil.java:391)
	at org.apache.axis2.databinding.utils.BeanUtil.processObject(BeanUtil.java:655)
	at org.apache.axis2.databinding.utils.BeanUtil.ProcessElement(BeanUtil.java:603)
	at org.apache.axis2.databinding.utils.BeanUtil.deserialize(BeanUtil.java:535)
	at org.apache.axis2.rpc.client.RPCServiceClient.invokeBlocking(RPCServiceClient.java:103)
	at de.wsTester.TestClient.main(TestClient.java:29)

Zeile 29 ist die letze .. d.h., dass er irgednwie beim umbauen der Antwort nen Problem hat :-/

den Rückgabetyp habe ich ordnungsgemäß als TransportContainer.class definiert .. aber warum zum Teufel kann er damit nicht umgehen?
 
Hallo,

ich vermute die NullPointer-Exception aus deinem ersten Thread-Beitrag kommt daher, dass du das HotelArray hotels[] nicht initialisiert hast, z. B. mit Hotel[] hotels = new Hotel[100];

Daher wird beim Aufruf der findHotels()-Methode die Exception geworfen.


Gruss
Toni
 
Hallo. Das gleiche Problem habe ich auch. Wie hast Du es denn gelöst? Und hast Du auch mit dem Buch "Java Web Services mit Apache Axis2" gearbeitet?
 
Hi,

manche Probleme erscheinen komplizierte als die Lösung nachher ist. Ich habe gleiches Problem und gleiches Buch. Ich habe im Clientprogramm die folgende Zeile hinsichtlich des Namespace korrigiert:

QName opFindHotel = new QName("http://axishotels.de", "findHotel");

Im Original wird "http://axishotels.de/xsd" verwendet. Nachdem ich das geändert habe, läuft auch der Client.

Tschau Lutz
 
Hallo hallo.
Danke für die Antwort. Habe das Problem mittlerweile lösen können. Ursache war, daß ich mich zu strikt an die Quelltexte im Buch gehalten habe - anstatt mal'n bißchen drumherum zu lesen. So habe ich natürlich die falsche services.xml erstellt und dann die flasche wsdl. Sowas kommt von sowas.
 
Zurück