Forum Discussion

MMehalso's avatar
MMehalso
Occasional Contributor
14 years ago

Mock Services - Multiple MockAsWarServlets

Hey guys -

Let me first-off say thanks a ton for getting the 'Deploy as WAR' functionality working for WebLogic. We've been using your product for some time with a large enterprise client and have been forced to use some workarounds to really integrate soapUI mock services into our QA and integration environments. I think that getting a lot of these issues ironed out will go a long way towards making your product the de facto standard for service stubs, at least with us and our clients.

So anyway, cutting to the chase:

The best way we've been able to package and deploy the soapUI-generated WARs is to bundle them up in an .EAR file before deploying to WebLogic. When deploying strictly as a WAR, we ran into countless classloading issues due to conflicts with several of the base XML packages included in WLS. This includes a small manual step, obviously, but is worth it to us if we can get a good process going for creating, modifying, and deploying these services.

The only problem we ran into, though, is that we're trying to use multiple projects (and therefore multiple MockAsWarServlets) in the same JVM. The problem here is that, during initialization, the MockAsWarServlet creates a new MockServletSoapUICore during initialization and stores it statically in the SoapUI class.

SoapUI.setServletCore(new MockServletSoapUICore(getServletContext(), true)

All further requests to get the core object, which then points back to the servlet and list of mock runners, goes through the static SoapUI class.

getMockServletCore().dispatchRequest(request, response)

So say we have two different projects running under the same ear on the same server. The first servlet that gets hit initializes and executes fine. The second servlet that gets hit also initializes and executes fine, but during initialization, this second call replaces the SoapUI class's SoapUICore object with a new one. So now if we go back and try to hit the first web service, we never get to it as the mock runner is never found during request execution (This also is not thread-safe, but that's not directly giving us any trouble right now).

I went in and resolved the issue locally with a small code change to your source. Rather than store the SoapUICore object on the SoapUI static class, I just added a member to the MockAsWarServlet class. That way, each servlet has its own SoapUI core, and we don't have any conflicts when multiple are running. Not sure this is the best way to go, though, as the DefaultSoapUICore class looks like a heavyweight. It'd be nice if multiple projects/servlets could share the same core, but without overwriting / interfering with eachother. Do you think you all can resolve this in a future release? Our project is able to continue with the patched MockAsWarServlet for now, but to sell this to the entire enterprise, and future clients, we really need something that works right out of the box.

Here's a summary of the changes I made to MockAsWarServlet
Added a member:

private MockServletSoapUICore serlvetsCore;


Added a setter:

protected void setMockServletCore(MockServletSoapUICore core)
{
this.servletsCore = core;
}


Replaced calls to SoapUI.setSoapUICore with:

setMockServletCore(core)


Replaced getter:

protected MockServletSoapUICore getMockServletCore()
{
return this.servletsCore;
}


Thanks for your help!

Matt
  • Hi Matt,

    thanks for this!

    I'm not sure this is the right way to go, since some internal SoapUI classes access the soapUI core via SoapUI.getSoapUICore() - I know this is a bad design but we have to live with it for now until we can refactor the whole core infrastructure..

    One alternative would be to create and set the core only if it isn't already there, otherwise just use the existing one. I've added this to the current sources, this will be in the upcoming nightly build, maybe you can give it a try to see if it works ok in your setup!?

    regards!

    /Ole
    eviware.com
  • MMehalso's avatar
    MMehalso
    Occasional Contributor
    Hey Ole,

    Thanks for the reply! I agree, what I posted is not the right way to go; we were just going for a quick patch to move along some tests.
    And we obviously like the design and product you guys have put together, we're just being picky about matching it to our needs

    I'll definitely give the nightly build a shot. The only problem, I think, is that the MockServletSoapUICore accesses it's outer class object - the actual servlet instantiation - to look for the appropriate mock runner for an incoming request.

    So if we have a single *Core object, it's can only access the mock services associated with it's outer servlet. An example would be a request to servlet #2 after servlet #1 has already initialized and created it's SoapUI Core:

    Request->Servlet #2->SoapUICore->Servlet #1->mockRunners --- mock runner not found

    The problem is here & here:

    /* */ public MockRunner[] getMockRunners()
    /* */ {
    /* 332 */ return ((MockRunner[])MockAsWarServlet.this.mockRunners.toArray(new MockRunner[MockAsWarServlet.this.mockRunners.size()]));
    /* */ }



    /* */ public boolean hasRunningMock(MockService mockService)
    /* */ {
    /* 337 */ for (MockRunner runner : MockAsWarServlet.this.mockRunners)
    /* */ {
    /* 339 */ if (runner.getMockService() == mockService)
    /* */ {
    /* 341 */ return true;
    /* */ }
    /* */ }
    /* */
    /* 345 */ return false;
    /* */ }


    I think there are two options for a quick fix -
    1. Store all the MockRunners in the MockServletSoapUICore object instead of in each servlet. That way you have a single list holding services from, potentially, multiple projects.
    2. Rather than access the mockRunners list by reference to the outer class object, (i.e. MockAsWarServlet.this.mockRunners), pass them as a parameter to the MockServetSoapUICore's dispatchRequest() method. That way you have a single SoapUICore, which the static SoapUI class knows about, and the core object can just use the provided mock runner list to decide how to execute the incoming request. That way, the core really shouldn't have to know about any of the servlets at all... strong cohesion & low coupling

    I may give #2 a shot as it's a relatively simple change.

    Thanks again!

    Matt
  • MMehalso's avatar
    MMehalso
    Occasional Contributor
    Hey Ole -

    I actually went with #1 from above, combined with the fix you made in the nightly build. All I really needed to do was move the list of MockRunner's into the MockServletSoapUICore class:

    ....(start snippet)....
    //Move from here:
    //private List<MockRunner> mockRunners = new ArrayList<MockRunner>();

    class MockServletSoapUICore extends DefaultSoapUICore implements MockEngine
    {
    private final ServletContext servletContext;

    //To here:
    private List<MockRunner> mockRunners = new ArrayList<MockRunner>();
    ....(end snippet)....


    Do you think that you all can make a similar change for the 4.0 release?

    Thanks,

    Matt
  • MMehalso's avatar
    MMehalso
    Occasional Contributor
    Hi Ole / soapUI Support!

    Have you had a chance to look at my last post? We were hoping you might be able to incorporate this small change into one of your nightly builds, so that we could use soapUI "out-of-the-box" as opposed to with our slightly customized soapUI jar.

    FYI - We are putting together a case with our client to use soapUI mock services across all platforms, groups, etc. (they currently utilize an enterprise service bus with upwards of 200 web services to connect various front-end and back-end systems). We'll be following a build & deployment process as described in this thread with WebLogic Server/Portal 10.3 as our main environment. Thought you guys might be interested in hearing about a large enterprise application of your mock services product!

    Thanks again for your help!

    Matt
  • Hi Matt,

    I'm sorry, I totally missed this amongst all beta related activities, I've applied your suggestion, it will be in either the upcoming nightly or the one after that.

    regards!

    /Ole
    eviware.com
  • MMehalso's avatar
    MMehalso
    Occasional Contributor
    Great, thanks Ole. Understand that you're probably very busy - we really appreciate the help & support!