Customizing FHEM in Richtung Java EE mit WebServices

Begonnen von fheddie, 29 August 2014, 10:46:45

Vorheriges Thema - Nächstes Thema

fheddie

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

rudolfkoenig

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.


betateilchen

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*

-----------------------
Formuliere die Aufgabe möglichst einfach und
setze die Lösung richtig um - dann wird es auch funktionieren.
-----------------------
Lesen gefährdet die Unwissenheit!

fheddie

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

ntruchsess

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
while (!asleep()) {sheep++};

rudolfkoenig

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.