Bug 56327

Summary: Adding non HTTP (e.g AJP) connector using MBeans is not possible
Product: Tomcat 8 Reporter: kiran <kgkiran>
Component: CatalinaAssignee: Tomcat Developers Mailing List <dev>
Status: RESOLVED FIXED    
Severity: normal    
Priority: P2    
Version: 8.0.x-trunk   
Target Milestone: ----   
Hardware: PC   
OS: Windows XP   
Attachments: Source code with the fix

Description kiran 2014-03-27 20:53:59 UTC
Created attachment 31451 [details]
Source code with the fix

Using MBeans (org.apache.catalina.mbeans.ServiceMBean) it is possible to add a connector during runtime.

API says:
 public void addConnector(String address, int port, boolean isAjp, boolean isSSL) 


Even adding AJP should be possible. However upon looking at the code, it is creating a Connector with default constructor that would set the protocolHandler to HttpProtocolHandler. In other words, to create an AJP connector, protocol should be available during the construction of the Connector.

It is a simple fix. 

   public void addConnector(String address, int port, boolean isAjp, boolean isSSL) throws MBeanException {
        
        Service service; 
        try {
            service = (Service)getManagedResource();
        } catch (InstanceNotFoundException e) {
            throw new MBeanException(e);
        } catch (RuntimeOperationsException e) {
            throw new MBeanException(e);
        } catch (InvalidTargetObjectTypeException e) {
            throw new MBeanException(e);
        }
        String protocol = isAjp ? "AJP/1.3" : "HTTP/1.1";
        

        // Pass the protocol here rather than setting it later
         Connector connector = new Connector(protocol);
   
        if ((address!=null) && (address.length()>0)) {
            connector.setProperty("address", address);
        }
        connector.setPort(port);
        connector.setSecure(isSSL);
        connector.setScheme(isSSL ? "https" : "http");

        service.addConnector(connector);       

    }
Comment 1 kiran 2014-03-27 23:26:29 UTC
Original Code

50     public void addConnector(String address, int port, boolean isAjp, boolean isSSL) throws MBeanException {
51         
52         Service service; 
53         try {
54             service = (Service)getManagedResource();
55         } catch (InstanceNotFoundException e) {
56             throw new MBeanException(e);
57         } catch (RuntimeOperationsException e) {
58             throw new MBeanException(e);
59         } catch (InvalidTargetObjectTypeException e) {
60             throw new MBeanException(e);
61         }
62         
63         Connector connector = new Connector();
64         if ((address!=null) && (address.length()>0)) {
65             connector.setProperty("address", address);
66         }
67         
68         connector.setPort(port);
69         connector.setProtocol(isAjp ? "AJP/1.3" : "HTTP/1.1");
70         connector.setSecure(isSSL);
71         connector.setScheme(isSSL ? "https" : "http");
72 
73         service.addConnector(connector); 


Line 63 is the problem. See the how Connector is created by ConnectorCreateRule vs in the ServiceMBean

Also interesting is the following code in org.apache.catalina.connector.Connector
   public Connector() {
        this(null);
    }

    public Connector(String protocol) {
        setProtocol(protocol);
        // Instantiate protocol handler
        try {
            Class<?> clazz = Class.forName(protocolHandlerClassName);
            this.protocolHandler = (ProtocolHandler) clazz.newInstance();
        } catch (Exception e) {
            log.error(sm.getString(
                    "coyoteConnector.protocolHandlerInstantiationFailed"), e);
        }
    }
protocolHandler is created in the beginning and is immutable and by default is Http1.1.
Comment 2 Mark Thomas 2014-04-04 21:43:34 UTC
Thanks for the report and the fix.

Patches should be provided in diff -u format rather than as full files as this makes them easier to review.

The patch has been applied to 8.0.x and will be included in 8.0.6 onwards.