Forum Discussion

afoo's avatar
afoo
New Contributor
10 years ago

Cannot run multiple virts on the same port

When attempting to start multiple virts on the same port, but with different paths (equivalent works fine in SoapUI Pro 4 & 5), I get the following error:

 

com.smartbear.servicev.core.model.SvpException: Port: 8888 is already occupied by virt virtName. Please choose another port.

I've tried multiple virts in the same project, as well as separate projects for each virt.  Since we have 10s to 100s of virts (depending on application), putting each of them on a different port isn't an option.

  • So, thinking about writing a java proxy to sit in front of ServiceV (and deciding that I still didn't like the idea of all the services on different ports), I came up with this solution:

     

    I created a new empty SOAP project, with an empty Virt, and added a "MockRunListener.onMockRequest" event handler, which loops through every service for every project in the current workspace, compares the path to the requested path, and dispatches as appropriate.  This pretty closely duplicates the old functionality, and since the original virts don't actually have to be running, they don't have to be modified to run on different ports.  Some example code without any error handling is below:

     

    import com.eviware.soapui.impl.wsdl.mock.WsdlMockService
    
    if (request.getAttribute("xReadyApiProxied")) {
    	return
    }
    
    for (project in runner.getMockContext().getMockService().getParent().getParent().getChildren()) {
    	for (service in project.getChildren())
    	{
    		if (service instanceof WsdlMockService) {
    			def ws = (WsdlMockService)service;
    	
    			if (request.getPathInfo() == ws.getPath()) {
    				log.info "Proxying request for " + request.getPathInfo() + " to " + project.name + " : " + ws.name
    
    				def runner = ws.getMockRunner();
    				if (runner == null) {
    					runner = ws.start();
    				}
    
    				request.setAttribute("xReadyApiProxied", true)
    				runner.dispatchRequest(request, response)
    			}
    		}
    	}
    }

     

  • Running multiple virts on same port is not supported any more. 

     

    To run multiple virts on the same port, user needs to configure different virt path or something similar for each virt, so those virts are distinguishable and requests can be directed towards the desired virt.  In most cases, this is cumbersome for the users to configure different path for each virt and change  the requests and test cases accordingly. Running each virt on different port is cleaner in that sense, even though it still requires to change the endpoint. Moreover, running each virt on its own port gives more capabilities, for example you can have different ssl settings for each virt. 

     

    But can you explain your scenario little bit more,  for example why it is not an option to run 100 virts on different ports? How do you configure those 100 virts running on same port distinguishable? Are those 100 virts kept running always or do you start those before running some tests?

    • afoo's avatar
      afoo
      New Contributor

      We have a fairly complex SOAP API, which separates functionality into multiple WSDLs, each of which is bound to a different path.  Apache CXF easily supports (and almost requires, because if we use different ports, we'd need a new Jetty instance) this binding, as do the several different appliances that we use for security in our production paths.  Depending on the specific deployment, some subset of these WSDLs are chosen, and the functionality may be reduced or altered.  We don't need or want another layer of ports (and our appliances can't handle that many ports in any case) to be managed on top of the path mapping we already have, and we can't easily build an uber-wsdl, since we'd need to create and manage a signifiant number of variations of that too.

       

      I guess we're sticking with SoapUI Pro 4.6.4 for now, since it's the last version that works consistently with multiple ports and composite projects.  Unless there are plans for a SoapUI Pro 5.1.3?

       

      • afoo's avatar
        afoo
        New Contributor

        So, thinking about writing a java proxy to sit in front of ServiceV (and deciding that I still didn't like the idea of all the services on different ports), I came up with this solution:

         

        I created a new empty SOAP project, with an empty Virt, and added a "MockRunListener.onMockRequest" event handler, which loops through every service for every project in the current workspace, compares the path to the requested path, and dispatches as appropriate.  This pretty closely duplicates the old functionality, and since the original virts don't actually have to be running, they don't have to be modified to run on different ports.  Some example code without any error handling is below:

         

        import com.eviware.soapui.impl.wsdl.mock.WsdlMockService
        
        if (request.getAttribute("xReadyApiProxied")) {
        	return
        }
        
        for (project in runner.getMockContext().getMockService().getParent().getParent().getChildren()) {
        	for (service in project.getChildren())
        	{
        		if (service instanceof WsdlMockService) {
        			def ws = (WsdlMockService)service;
        	
        			if (request.getPathInfo() == ws.getPath()) {
        				log.info "Proxying request for " + request.getPathInfo() + " to " + project.name + " : " + ws.name
        
        				def runner = ws.getMockRunner();
        				if (runner == null) {
        					runner = ws.start();
        				}
        
        				request.setAttribute("xReadyApiProxied", true)
        				runner.dispatchRequest(request, response)
        			}
        		}
        	}
        }