Where communities thrive


  • Join over 1.5M+ people
  • Join over 100K+ communities
  • Free without limits
  • Create your own community
People
Repo info
Activity
    jefkin
    @jefkin

    Ok, First of all, sorry for the huge post here. But I think I'm having trouble with dependency injection on a servlet class.
    The architecture we're using is to support a series (17) of remote database queries. These queries are in fact handled by SOAP web services, but behind a firewall the purpose of our appserver is to have a single point for crossing the fire wall, logging and validating the services.
    To accomplish this, I created a BaseServlet class and a base Query Service. Since most of the Servlet class is parsing the inputs and writing the transaction logs, while the individual query differences are pretty small. So BaseServlet implements the doGet() and doPost(). Then for each of our Queries we have a Servlet subclass that extends BaseServlet. Each defines it's own @Route annotation, and each adds an attribute that adds a dependency injected Service class.
    Well that is the plan, so far I've had a problem on the first one "PingServlet" which simply validates the SOAP web services are up. Anyway, class PingServlet extends BaseServlet, and simply defines it's Route and adds a dependency injected Service class like:

    /** 
     * @var Vendor\Project\Ping
     * @EnterpriseBean(name="Ping")
     */
    protected   $ping;

    I'm only kind-of sure this part works, as the initialize for the Ping class is called. However, the PingServlet, in handling the request, must call a function on the Service side, for example $this->ping->run($this->args, $this->dates); Since each Servlet will have a different class, I have a small function callService() each query-servlet must implement. And the BaseServlet in the doPost() calls $this->callService();
    due to logging/debugging, I know do Post arrives in the callService() and continues after it, but I neither get an error answer from the invocation of the supposedly dependency Injected Service nor does control ever arrive there, just a big silent no-op.
    So, to be clear, Although my original version of this, with a singular Servlet and Service, modeled on the HelloServlet in the example app, worked fine, I'm unclear about how to even proceed as there are no errors but no communication to the Service side either.
    Unless there's a quick fix to this or some bright Idea, I'll have to refactor this back towards the helloServlet that I began with, which, at least, was communicating to the Service side of things. But instead of several small simple Servlets, we'll need to have it all rolled into one, or do a lot of repeating myself across multiple classes.
    Any insight would be hugely appreciated.

    Tim Wagner
    @wagnert
    Can post the complete servlet class source here?
    jefkin
    @jefkin
    well that didn't work :(
    format wise, but I guess the code's there
    Bernhard Wick
    @wick-ed
    Hi there
    (shift+enter for line break) var code = "formatted";
    hmm
    There is a little markdown help in the bottom right
    code blocks work with backticks around them
    jefkin
    @jefkin
    lol let me delete those if i can
    Tim Wagner
    @wagnert
    Ok, this is the class right
    <?php
    
    namespace Vendor\Project;
    
    use AppserverIo\Http\HttpProtocol;
    use AppserverIo\Psr\Servlet\Http\HttpServlet;
    use AppserverIo\Psr\Servlet\Http\HttpServletRequestInterface;
    use AppserverIo\Psr\Servlet\Http\HttpServletResponseInterface;
    use AppserverIo\Psr\Servlet\ServletConfigInterface;
    
    /**
     * @Route(name="Ping", urlPattern={"/ping.do", "/RFC_PING/run/all/ping.do", "/ping.do"})
     */
    class PingServlet extends BaseServlet
    {
        /**
         * @var Vendor\Project\Ping
         * @EnterpriseBean(name="Ping")
         */
        protected $ping;
    
        /**
         * Ideally this will set the service value correctly so we can evoke the named attribute class. (Initializes
         * the servlet with the passed configuration)
         *
         * @param \AppserverIo\Psr\Servlet\ServletConfigInterface $servletConfig The servlet config to initialize with
         *
         * @throws \AppserverIo\Psr\Servlet\ServletException Is thrown if the configuration has errors
         * @return void
         */
        public function init(ServletConfigInterface $servletConfig)
        {
            $this->service = 'ping';
        }
    
        /**
         * This function calls the Service to fire the SOAP WS requests to SAP for the RFC.
         *
         * @param str $call The remote service function name to call
         * @return array
        */
        public function callService()
        {
            $this->text .= " Ping Servlet calling: [{$this->call}] on service [{$this->service}]\n";
            $results = $this->ping->{$this->call}($this->args, $this->dates);
            $message = var_export($results, true);
            $this->text .= " Ping Servlet call results: [\n{$results}\n]\n on service [{$this->service}]\n";
    
            if (!is_array($results))
            {
    
                $results    = [ $results ];
            }
            return $results;
        }
    }
    jefkin
    @jefkin
    yes looks like mine
    Tim Wagner
    @wagnert
    You've a service class below the META-INF folder that is called class Ping { ... } and has the annotation @Stateless for example?
    jefkin
    @jefkin
    yes, do you need that class too?
    Tim Wagner
    @wagnert
    Did you try to inject the system logger and log a message to proof that the callService() will be invoked on the POST request?
    jefkin
    @jefkin
    I was having issues with that on the Servelet side, so I'm saving the data in the $this->text, and appending that to the servelet Response in the doPost() function
    Tim Wagner
    @wagnert
    like
    class Test
    {
    
        /**
         * The system logger implementation.
         *
         * @var \AppserverIo\Logger\Logger
         * @EPB\Resource(lookup="php:global/log/System")
         */
        protected $systemLogger;
    
        public function doGet(HttpServletRequestInterface $servletRequest, HttpServletResponseInterface $servletResponse)
        {
            $this->systemLogger->error(__METHOD__);
        }
    }
    jefkin
    @jefkin
    results
    [{"RFC_PING":{"query-codes":[],"RUN_TIME":[]}}
    ]
    Base Servlet calling: [run] on service [ping.do]
    after call this->dates:
    ok, I can add that
    Tim Wagner
    @wagnert
    only to make sure if the method will be called or not ... on a first view, i can't see any error
    jefkin
    @jefkin
    Call to a member function error() on null in ...<path>cache/Vendor_Project_BaseServlet.php on line 117
    hmm I see $systemLogger is used in the example app in WEB-INF/classes/AppserverIo/Apps/Example/Servlets/AnnotatedServlet.php but slightly different anotation, just in case it's a version thing, switching to that
    @Resource(lookup="php:global/log/System")
    Tim Wagner
    @wagnert
    yes, sorry for that :-)
    jefkin
    @jefkin
    (error): Vendor\Project\BaseServlet::doGetDOPPELGAENGEROriginal []
    I will sprinkle that system logger error through my functions, -- does it work on META-INF side as well?
    jefkin
    @jefkin
    ah on the META-INF service side I"m already using $this->getInitialContext()->getSystemLogger()->info(); should I "UP" that to error?
    Tim Wagner
    @wagnert
    what do you mean with "UP"?
    jefkin
    @jefkin
    by up I meant moving it up to ->error() instead of ->info() Ok I am about to go in a status meeting now, be back soon
    Tim Wagner
    @wagnert
    All right :-)
    Tim Wagner
    @wagnert
    Hm, depends on the error level you defined in your META-INF/context.xml file. If you've set <param name="logLevel" type="string">info</param> ->info() should be enough
    jefkin
    @jefkin
    I'm going to upgrade to error to make sure that the response flow is parsimonious
    [2019-05-15 17:19:47] - host.com (error): Vendor\Project\BaseServlet::doGetDOPPELGAENGEROriginal []
    [2019-05-15 17:19:47] - host.com (error): Vendor\Project\BaseServlet::responderDOPPELGAENGEROriginal []
    [2019-05-15 17:19:47] - host.com (info): Vendor\Project\AbstractProcessor::postConstructDOPPELGAENGEROriginal has successfully been invoked by @PostConstruct annotation []
    [2019-05-15 17:19:47] - host.com (error): JWB Ping::initialize() []
    but the run method is not invoked or at least not logged.
    jefkin
    @jefkin
    I've checked the system error log, and the php error log and the app error logs, no errors but also no connection beyond the init.
    jefkin
    @jefkin
    I'm really at a loss at this point, I'm saving my work at this point on a stub branch and moving back to the simple one servlet version I had originally
    Tim Wagner
    @wagnert
    Hm, can you give me access to the repo?
    jefkin
    @jefkin
    well, I'll have to check with the boss probably some NDA's might be needed, etc. but I'm in get'er'done mode so I'm thinking it's probably best to shelve this for now.
    Tim Wagner
    @wagnert
    I'm sure that this is only a small thing to fix, but it's quite hard to fix it here ... :(
    maybe it'll be enough if you can ZIP the WEB-INF folder with the servlets ...
    jefkin
    @jefkin
    I can do that and revise the sensitive stuff, is there an email I can send it to?
    Tim Wagner
    @wagnert
    yes, sent it to tw@appserver.io :-)
    jefkin
    @jefkin
    I'm now pretty sure the issue isn't on the WEB-INF side, because I'm fully rolled back to single servlet class, and when I invoke on the dependency injected Service, i see the init called, but I do not see my specified function called, even when hard-coded like: $this->ping->run($this->args, $this->dates); ... it seems, regardless of how I call it, the service object's init () runs, but not the service action e.g. run() ... I did notice that the example apps have servlet side and service side in different namespaces, reworked my code that way, and still get the init to fire but not the direct function I'm calling
    Tim Wagner
    @wagnert
    @jefkin I've sent you some emails, i think there may be an issue with the classname Ping, so please try rename it to PingService for example ..
    jefkin
    @jefkin
    I'll give that a try, though I tried Ping2 which didn't seem to resolve the issue, but I'll let you know
    Tim Wagner
    @wagnert
    Ok, otherwise have a look at the mails i sent you :-)
    jefkin
    @jefkin

    So I want to use dependency injection in the servlet for a class that lives in the common directory of my app, I tried doing:
    /**

     *  The HTML Writer for logs.
     *
     *  @var Vendor\Project\Utilities\HtmlWriter;
     *  @EnterpriseBean(name="HtmlWriter") 
     */
    protected   $htmlWriter;

    which compiles ok, but on execution of the servelet we get a fatal error in the application error log that says:

    [2019-05-16 19:22:18] - host.com (error): PHP Exception: exception 'Exception' with message 'Requested value php:global/combined-appserver/sapwebremote/HtmlWriter has not been bound to naming directory php:' in /opt/appserver/src/AppserverIo/Appserver/Naming/NamingDirectory.php:213
    so is there a way on the WEB-INF side to name a dependancy injection similar to how we do with epb.xml on the service side?
    Tim Wagner
    @wagnert
    Hi, depends on the appserver version you use?