Hallo, Leute.
Ich (erfahrener JEE-Entwickler, absoluter Perl-Newbie) möchte gern meinen FHEM-Server, der auf einem Raspberry PI läuft, mit einer JEE-Anwendung verheiraten. Hierzu plane ich WebServices zu benutzen. Ich habe also mal testweise eine der (Stateless) EJBs in meinem JBoss (7) als WebService zur Verfügung gestellt:
------------------------------------------------------------------------------------------------------------------------------------------------>schnipp
package de.gravitex.bpmtest.ejb.logic.wstest;
import javax.ejb.Local;
import javax.ejb.Remote;
import javax.ejb.Stateless;
import javax.jws.WebMethod;
import javax.jws.WebService;
@Stateless(name = "WSTest")
@Local(WSTest.class)
@Remote(WSTestRemote.class)
@WebService(name = "HelloWorldWS", targetNamespace="http://wstest.logic.ejb.bpmtest.gravitex.de/")
public class WSTestBean implements WSTest {
@WebMethod
public void triggerWebserviceSimple() {
System.out.println(" ### triggerWebserviceSimple ### ");
}
}
------------------------------------------------------------------------------------------------------------------------------------------------<schnapp
Den zur Verfügung gestellten WebService kann ich problemlso von einem Java-Client aus ansprechen:
------------------------------------------------------------------------------------------------------------------------------------------------>schnipp
JaxWsProxyFactoryBean factory = new JaxWsProxyFactoryBean();
factory.getInInterceptors().add(new LoggingInInterceptor());
factory.getOutInterceptors().add(new LoggingOutInterceptor());
factory.setServiceClass(WSTestRemote.class);
factory.setAddress("http://localhost:8484/bpm-ejb-1.0-SNAPSHOT/HelloWorldWS?wsdl");
WSTestRemote ws = (WSTestRemote) factory.create();
ws.triggerWebserviceSimple();
------------------------------------------------------------------------------------------------------------------------------------------------<schnapp
In der clientseitigen Java-Konsole erscheint folgendes (dieses nur zur Info, auf der Java-Seite habe ich ja kein Problem):
------------------------------------------------------------------------------------------------------------------------------------------------>schnipp
Aug 29, 2014 10:28:47 AM org.apache.cxf.service.factory.ReflectionServiceFactoryBean buildServiceFromClass
INFO: Creating Service {http://wstest.logic.ejb.bpmtest.gravitex.de/}WSTestRemoteService from class de.gravitex.bpmtest.ejb.logic.wstest.WSTestRemote
Aug 29, 2014 10:28:47 AM org.apache.cxf.services.WSTestRemoteService.WSTestRemotePort.WSTestRemote
INFO: Outbound Message
ID: 1
Address: http://localhost:8484/bpm-ejb-1.0-SNAPSHOT/HelloWorldWS?wsdl
Encoding: UTF-8
Http-Method: POST
Content-Type: text/xml
Headers: {Accept=[*/*], SOAPAction=[""]}
Payload: <soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"><soap:Body><ns2:triggerWebserviceSimple xmlns:ns2="http://wstest.logic.ejb.bpmtest.gravitex.de/"/></soap:Body></soap:Envelope>
Aug 29, 2014 10:28:47 AM org.apache.cxf.services.WSTestRemoteService.WSTestRemotePort.WSTestRemote
INFO: Inbound Message
ID: 1
Response-Code: 200
Encoding: UTF-8
Content-Type: text/xml;charset=UTF-8
Headers: {Content-Length=[204], content-type=[text/xml;charset=UTF-8], Date=[Fri, 29 Aug 2014 08:28:47 GMT], Server=[Apache-Coyote/1.1]}
Payload: <soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"><soap:Body><ns2:triggerWebserviceSimpleResponse xmlns:ns2="http://wstest.logic.ejb.bpmtest.gravitex.de/"/></soap:Body></soap:Envelope>
------------------------------------------------------------------------------------------------------------------------------------------------<schnapp
Nun möchte ich meine FHEM-Installation so customizen, dass an der Codestelle, wo er rausloggt, dass z.B. ein Fenster geöffnet wurde, dieser WebService aufgerufen wird. Das passiert dann natürlich mit Parametern (Komponenten-Name, Status offen/zu o.ä.), aber das habe ich aber wegen der Übersichtlichkeit erstmal außen vor gelassen. Ich verwende das folgende Perl-Skript:
------------------------------------------------------------------------------------------------------------------------------------------------>schnipp
#!/usr/bin/perl -w
# declare usage of SOAP::Lite
use SOAP::Lite;
sub SOAP::Transport::HTTP::Client::get_basic_credentials {
return 'pruser' => 'pruser';
}
# declare the SOAP endpoint here
my $soap = SOAP::Lite
-> proxy('http://localhost:8484/bpm-ejb-1.0-SNAPSHOT/HelloWorldWS?wsdl');
# calling the function
my $method = SOAP::Data->name('triggerWebserviceSimple')->attr({xmlns => 'http://wstest.logic.ejb.bpmtest.gravitex.de/'});
my @params = ();
# invoke the SOAP call
$soap->call($method => @params);
------------------------------------------------------------------------------------------------------------------------------------------------<schnapp
Die Anfrage erreicht den JBoss auch, allerdings wirft der Server den folgenden Fehler:
------------------------------------------------------------------------------------------------------------------------------------------------>schnipp
10:38:22,609 WARNING [org.apache.cxf.phase.PhaseInterceptorChain] (http-/0.0.0.0:8484-1) Interceptor for {http://wstest.logic.ejb.bpmtest.gravitex.de/}WSTestBeanService#{http://wstest.logic.ejb.bpmtest.gravitex.de/}triggerWebserviceSimple has thrown exception, unwinding now: org.apache.cxf.intercept
or.Fault: The given SOAPAction http://wstest.logic.ejb.bpmtest.gravitex.de/#triggerWebserviceSimple does not match an operation.
at org.apache.cxf.binding.soap.interceptor.SoapActionInInterceptor$SoapActionInAttemptTwoInterceptor.handleMessage(SoapActionInInterceptor.java:188)
at org.apache.cxf.binding.soap.interceptor.SoapActionInInterceptor$SoapActionInAttemptTwoInterceptor.handleMessage(SoapActionInInterceptor.java:162)
at org.apache.cxf.phase.PhaseInterceptorChain.doIntercept(PhaseInterceptorChain.java:262)
at org.apache.cxf.transport.ChainInitiationObserver.onMessage(ChainInitiationObserver.java:121)
at org.apache.cxf.transport.http.AbstractHTTPDestination.invoke(AbstractHTTPDestination.java:237)
at org.jboss.wsf.stack.cxf.RequestHandlerImpl.handleHttpRequest(RequestHandlerImpl.java:95)
at org.jboss.wsf.stack.cxf.transport.ServletHelper.callRequestHandler(ServletHelper.java:156)
at org.jboss.wsf.stack.cxf.CXFServletExt.invoke(CXFServletExt.java:87)
at org.apache.cxf.transport.servlet.AbstractHTTPServlet.handleRequest(AbstractHTTPServlet.java:225)
at org.apache.cxf.transport.servlet.AbstractHTTPServlet.doPost(AbstractHTTPServlet.java:145)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:754) [jboss-servlet-api_3.0_spec-1.0.2.Final.jar:1.0.2.Final]
at org.jboss.wsf.stack.cxf.CXFServletExt.service(CXFServletExt.java:135)
at org.jboss.wsf.spi.deployment.WSFServlet.service(WSFServlet.java:140) [jbossws-spi-2.1.1.Final.jar:2.1.1.Final]
at javax.servlet.http.HttpServlet.service(HttpServlet.java:847) [jboss-servlet-api_3.0_spec-1.0.2.Final.jar:1.0.2.Final]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:295)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:214)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:230)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:149)
at org.jboss.as.web.security.SecurityContextAssociationValve.invoke(SecurityContextAssociationValve.java:169)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:145)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:97)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:102)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:336)
at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:856)
at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:653)
at org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:920)
at java.lang.Thread.run(Thread.java:745) [rt.jar:1.7.0_60]
------------------------------------------------------------------------------------------------------------------------------------------------<schnapp
Ich hab hierzu auch schon massiv gegoogled, hat mich aber alles nicht so weitergebracht. Ich weiß auch nicht so genau, ob der Fehler in der Java- oder der Perlwelt liegt,
allerdings funzt die Java-Seite ja. Vielleicht hat jemand eine Idee?
Danke schonmal,
Stefan
Meiner zugegebenermassen nicht unvoreingenommenen Meinung nach sollte man die Finger von Webservices (insb. mit SOAP::Lite) lassen, es sei denn man hat grenzenlos viel Zeit und Lust um sich mit Problemen zu befassen die bei anderen Protokollen nicht existieren.
Zitat von: rudolfkoenig am 29 August 2014, 11:03:56
sollte man die Finger von Webservices (insb. mit SOAP::Lite) lassen, es sei denn man hat grenzenlos viel Zeit und Lust um sich mit Problemen zu befassen die bei anderen Protokollen nicht existieren.
*unterschreib*
Hi.
Danke schon mal...dann weiß ich das. Also kommt auf den PI zusätzlich zur FHEM-Installation ein kleines Java-Programm, welches den WebService aufruft (und seinerseits von Perl aufgerufen wird), dann bleibe ich mit dem WS in der Java-Welt, sollte keine Probleme geben.
Danke,
Stefan
Zitat von: rudolfkoenig am 29 August 2014, 11:03:56
Meiner zugegebenermassen nicht unvoreingenommenen Meinung nach sollte man die Finger von Webservices (insb. mit SOAP::Lite) lassen, es sei denn man hat grenzenlos viel Zeit und Lust um sich mit Problemen zu befassen die bei anderen Protokollen nicht existieren.
Für SOAP kann ich mich der Meinung anschließen, das ist vom Protokoll her nicht trivial und man ist der interoperabilität der verwendeten Frameworks (hier SOAP::Lite <-> JAXWS) ziemlich bedingungslos ausgeliefert. Wenn SOAP::Lite noch nicht den nötigen Reifegrad hat, dann wirst Du da recht tief einsteigen müssen. (Mich könnte das schon reizen, aber ich habe aktuell schon genug Baustellen...)
Wenn es Webservices sein sollen dann würde ich Dir REST ans Herz legen, dass ist seit JEE-6 auch ganz einfach zu implementieren und ist vom Protokoll her simpel genug um den nötigen HTTP-Request in Perl zur Not einfach selber zu basteln.
Gruß,
Norbert
Wenn SOAP::Lite noch nicht den nötigen Reifegrad hat
Ich habe SOAP::Lite zuletzt vor etwa 10 Jahren naeher angeschaut. Ich habe zwar nach wenigen Tagen(!) erreicht, was ich wollte (ein Oracle Webservice-Call zufriedenzustellen), aber ich habe beschlosssen fuer weitere Projekte schon im Vorfeld alles zu tun, um SOAP::Lite zu vermeiden. Das Wort "Lite" ist Euphemismus pur.