Where communities thrive


  • Join over 1.5M+ people
  • Join over 100K+ communities
  • Free without limits
  • Create your own community
People
Repo info
Activity
    Tim Wagner
    @wagnert
    You're welcome :-)
    jefkin
    @jefkin
    Getting a strange magic error from DOPPELGAENGER -> exception 'AppserverIo\Psr\Servlet\ServletException' with message 'Please configure an error page for status code 500' in /opt/appserver/src/AppserverIo/Appserver/ServletEngine/Utils/ErrorUtil.php:291 Stack trace: #0
    /opt/appserver/src/AppserverIo/Appserver/ServletEngine/RequestHandler.php(263): AppserverIo\Appserver\ServletEngine\Utils\ErrorUtil->handleErrors(Object(AppserverIo\Appserver\ServletEngine\RequestHandler),
    Object(AppserverIo\Appserver\ServletEngine\Http\Request), Object(AppserverIo\Appserver\ServletEngine\Http\Response)) #1 [internal function]: AppserverIo\Appserver\ServletEngine\RequestHandler->shutdown() #2 {main}
    --- php error log reports: [09-May-2019 15:44:53 Europe/Berlin] PHP Fatal error: Cannot redeclare PowerThreeWeb\SapWebRemote\PingServlet::doGet() in /opt/appserver/var/tmp/localhost/sapwebremote/cache/PowerThreeWeb_SapWebRemote_PingServlet.php on line 85 -- I examined the cached class file and indeed the DOPPLE version of the doGet existed, but the original version lacked the doGetDOPPELGAENGEROriginal style rewrite that occured in several of the other classes that I looked at in the cache directory. I'm sure there's something I'm doing wrong but I'm not sure where to go at this point. Is this a common pitfall? Are there some regular places I should look for logs or info about he DoPPELGAENGER process?
    jefkin
    @jefkin
    I have discovered the source of the problem in my code I had more than one space between 'function' and 'doGet' ... note that an extra space between 'public' and 'function' doesn't cause the issue, but an extra space (or more) between 'function' and '<the actual function name>' creates this issue.
    jefkin
    @jefkin
    every function in our original code had multiple spaces between 'function' and '<the actual function name>', so needless to say, I'll be reformatting a lot of function declarations :-/
    Tim Wagner
    @wagnert
    Hi, sorry to hear that. We’lli this with this with the nex release if you’ll add an Github issue 🙂
    jefkin
    @jefkin
    added the issue for you appserver-io/appserver#1121
    Tim Wagner
    @wagnert
    @jefkin Thanks, appreciate it :-)
    jefkin
    @jefkin
    Two Questions; earlier this week, you mentioned $application->getDataDir() but I have two issues with that, first, I can find no mention of 'getDataDir' in the appserver.io code, I found a getTmpDir which seems to be the right one for the current version of appserver.io I'm using, as the appserver.xml contains a container with this defined: <host name="localhost" appBase="webapps" deployBase="deploy" tmpBase="var/tmp/localhost" /> ... Confirmation on that would be nice, however the second question is how to get the application injected into a stateless enterprise bean, I have this:
    /**  
     * The application instance that provides the entity manager.
     *
     * @var \AppserverIo\Appserver\Application\Application
     * @Resource(name="Application")
     */
    protected   $application; 
    Tim Wagner
    @wagnert
    Hi @jefkin Checkout this for the Application::getDataDir() method. Regarding the injection you're right, this would be the way, for more information you can checkout our example app :-)
    jefkin
    @jefkin
    so, I'm checking and my version of appserver.io doesn't have that DataDir, but I assume that TmpDir will work, I'm currently looking at your example app in git hub and seeing if that lines up to the code I've got to use on the server.
    Tim Wagner
    @wagnert
    Hm, what version of appserver.io are you using?
    make sure, you're using version 1.1.20 ... https://github.com/appserver-io/appserver/releases ...
    jefkin
    @jefkin
    hmm my sys admins picked 1.1.4
    that's what your site shows ... would I have any issues using that?
    I get that it's not bleeding edge
    So ... I do see your example/META-INF/classes/AppserverIo/Apps/Example/Services/AbstractProcessor.php in this version, I assume I just need to inherit from that and add the epb.xml file tweaked a bit
    Tim Wagner
    @wagnert
    So we recommend choosing 1.1.20, but yes it should be enough to inheri from it 🙂
    jefkin
    @jefkin
    So I have another semi random question. In the docs: https://docs.appserver.io/documentation/webserver it suggests you can enable a module: PhpModule in order to get the standard $_GET $_POST, which we needed for handling posted data, unless there's some other way to get the post data? Is there an api function to get it directly? ... the reason I ask is because when I added the configuration: <module type="\AppserverIo\WebServer\Modules\PhpModule"/> to the etc/appserver/appserver.xml, suddenly my app wouldn't work .. it would start but then silently fail. So I did a scan of the source tree and in ./vendor/appserver-io/webserver/CHANGELOG.md, I found this note: * Remove deprecated PhpModule and related classes
    So i'm guessing that there must be either something else I'm missing in the configuration, or a simpler (cleaner?) way to access get and post data for our servelets
    I saw this file: webapps/example/WEB-INF/classes/AppserverIo/Apps/Example/Servlets/WebserviceServlet.php which seems to do some of the things we need to do with our servlets, and it uses an api thing: $servletRequest->getParameterMap(), I've removed the PhpModule and I'll try some debugging on that object.
    Tim Wagner
    @wagnert
    Hi, the PhpModule is old stuff from version 1.0 and should not be used anymore. If you need some $_GET, $_POST stuff i would recommend to use the $servletRequest->getServerVar($name) and '$servletRequest->getParameter($name)' methods, whereas the last one contains all GET and POST variables.
    jefkin
    @jefkin
    thanks, I'll check those out
    Tim Wagner
    @wagnert
    Perfect :-)
    jefkin
    @jefkin
    just a sanity question, on the architecture, specifically the WEB_INF side of things, if a series of 15 calls to a servlet happen over a long period of time, I assume the the same servlet could handle each of them in turn (not sure it does though). However if 100 requests all happen overtop of each other, I assume the appserver will spawn copies, as needed or simply queue the requests, is my assumption close to accurate?
    Tim Wagner
    @wagnert
    @jefkin You've to start as many threads as necessary to handle the request. If you've long running requests on some servlets, you should take that in to account, there is no spawning, sorry. The configuration can be done in etc/appserver/appserver.xml, look for workerNumber, workerAcceptMin+ workerAcceptMax configurations in HTTP as well as HTTPS server.
    jefkin
    @jefkin
    so servlets are not recycled then, correct?
    Tim Wagner
    @wagnert
    Servlets will be created on every request, means not recycled, that's true.
    Sorry, the instances will be created once, but on each request a new copy will handle the request ... so there is some kind of recycling, yes :-)
    jefkin
    @jefkin
    ok thanks, yah i was just a little unclear after watching a gif image representation of appserver.io, and if they persisted, that would have potentially thrown a monkey-wrench in our design ... soo ... whew! ;D
    Tim Wagner
    @wagnert
    it would be possible to implement a persisent servlet that will be passed between the requests as real reference, but we'll NOT recommend to do that because of memory things you have to be aware of
    jefkin
    @jefkin
    yeah :) ... I think out-of-box will work fine, thanks for the late night (I asusme Germany) answer :D
    Tim Wagner
    @wagnert
    Yes, we're in germany :-) You're welcome @jefkin
    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: