On Wed, Dec 13, 2023 at 9:43 PM Daniel Skiles
<dski...@docfinity.com.invalid> wrote:
>
> The object and operation I'm trying to address is Catalina -->
> ProtocolHandler --> <port> --> <host> --> operations --> addSslHostConfig.
>
> The parameters are an SslHostConfig object and the boolean value "true".
>
> The operation is "addSslHostConfig".
>
> The code I sent in the previous message works 100% of the time in 9.0.82.
> In 9.0.83, it works about 50% of the time.  I can always query that the
> operation exists, but roughly half the time it will fail with a JMX
> exception saying that the operation does not exist.
>
> I am not positive, but I believe the behavior in 9.0.83 might have to do
> with the fact that the catalina java code now has a one argument and two
> argument variant of the same method.

I'm pretty sure you got the explanation right. It is very similar to
using reflection here. You're doing the lookup based on the method
name, which matches something. However, if you want to avoid an error,
you also have to check that the arguments match, otherwise you're
going to randomly pick one of the two methods and fail half the time.

Rémy

> On Wed, Dec 13, 2023 at 10:27 AM Christopher Schultz <
> ch...@christopherschultz.net> wrote:
>
> > Daniel,
> >
> > On 12/12/23 19:45, Daniel Skiles wrote:
> > > I apologize for it being a bit rough - it's what I was using to
> > > troubleshoot locally.
> > >
> > > import static java.util.Objects.nonNull;
> > >
> > > import java.lang.management.ManagementFactory;
> > > import java.util.Arrays;
> > > import java.util.HashMap;
> > > import java.util.Map;
> > > import java.util.Optional;
> > > import java.util.function.Predicate;
> > >
> > > import javax.management.MBeanInfo;
> > > import javax.management.MBeanOperationInfo;
> > > import javax.management.MBeanServer;
> > > import javax.management.ObjectName;
> > >
> > > import org.apache.logging.log4j.LogManager;
> > > import org.apache.logging.log4j.Logger;
> > > import org.apache.tomcat.util.net.SSLHostConfig;
> > > import org.apache.tomcat.util.net.SSLHostConfigCertificate;
> > > import org.apache.tomcat.util.net.SSLHostConfigCertificate.Type;
> > >
> > > @javax.annotation.ManagedBean
> > > public class MbeanFailure {
> > > private static final Logger LOGGER = LogManager.getLogger();
> > >
> > > private static final String LOCALHOST = "127.0.0.1";
> > > private static final String SUBTYPE = "subType";
> > > private static final String ADD_SSL_HOST_CONFIG_OP = "addSslHostConfig";
> > >
> > > private static final Predicate<ObjectName> NOT_LOCALHOST =
> > Predicate.not(on
> > > ->
> > >
> > Optional.ofNullable(on).map(ObjectName::getCanonicalName).orElse("").contains(LOCALHOST));
> > > private static final Predicate<ObjectName>  NOT_SUBTYPE =
> > Predicate.not(on
> > > ->
> > >
> > Optional.ofNullable(on).map(ObjectName::getCanonicalName).orElse("").contains(SUBTYPE));
> > >
> > > @javax.annotation.PostConstruct
> > > public void run() throws Exception {
> > > final MBeanServer server = ManagementFactory.getPlatformMBeanServer();
> > >
> > > final SSLHostConfig config = new SSLHostConfig();
> > >
> > > config.setProtocols("TLSv1.2");
> > > config.setHostName("test.test.com");
> > > config.setCiphers("TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256");
> > >
> > > final SSLHostConfigCertificate cert = new
> > SSLHostConfigCertificate(config,
> > > Type.UNDEFINED);
> > >
> > > config.addCertificate(cert);
> > > final Map<MBeanServer, ObjectName> references =
> > getObjectReferences(server,
> > > "ProtocolHandler");
> > >
> > > references.forEach((s, op) -> invoke(s, op, ADD_SSL_HOST_CONFIG_OP, new
> > > Object[] {config}, new String[]
> > {SSLHostConfig.class.getCanonicalName()}));
> > > }
> > >
> > > public Map<MBeanServer, ObjectName> getObjectReferences(final MBeanServer
> > > server, final String discriminator) {
> > >
> > > final  Map<MBeanServer, ObjectName> results = new HashMap<>();
> > >
> > > final Predicate<ObjectName> extendedFilters =
> > > NOT_LOCALHOST.and(NOT_SUBTYPE);
> > >
> > > final Optional<ObjectName> candidate = server.queryNames(null,
> > > null).stream()
> > > .filter(on -> nonNull(on.getCanonicalName()))
> > > .filter(on -> on.getCanonicalName().contains(discriminator))
> > > .filter(extendedFilters)
> > > .findAny();
> > >
> > > candidate.ifPresent(on -> results.put(server, on));
> > >
> > > return Map.copyOf(results);
> > > }
> > >
> > > public Object invoke(final MBeanServer server, final ObjectName
> > objectName,
> > > final String method, final Object[] params, final String[] signature) {
> > > try {
> > > //This should return addSslHostConfig(SSLHostConfig, boolean)
> > > final MBeanInfo info = server.getMBeanInfo(objectName);
> > >
> > > final MBeanOperationInfo methodInfo = Arrays.stream(info.getOperations())
> > > .filter(i -> i.getName().equals(method))
> > > .findAny()
> > > .orElseThrow(() -> new RuntimeException("Could not find method  named" +
> > > method));
> > >
> > > LOGGER.error("Found available operation {}", methodInfo);
> > >
> > > final Object result = server.invoke(objectName, method, params,
> > signature);
> > > return result;
> > > } catch (final Exception e) {
> > > throw new RuntimeException("Error invoking " + method + " with params " +
> > > Arrays.toString(params) + " and signature " + Arrays.toString(signature),
> > > e);
> > > }
> > > }
> > > }
> >
> > What objctName do you think you are addressing, here? What parameters
> > are you passing it and what types? What parameters and types are
> > expected by the operation you are trying to invoke?
> >
> > -chris
> >
> > > On Fri, Dec 8, 2023 at 4:55 PM Christopher Schultz <
> > > ch...@christopherschultz.net> wrote:
> > >
> > >> Daniel,
> > >>
> > >> On 12/7/23 13:25, Daniel Skiles wrote:
> > >>> All,
> > >>> I've been doing some testing, and I'm pretty sure the addSslHostConfig
> > >>> operation on ProtocolHandler is busted in 9.0.83.
> > >>>
> > >>> In versions prior to 9.0.82, you can call the operation with a single
> > >>> argument of type SSLHostConfig.
> > >>>
> > >>> In 9.0.82, that contract seems to have been broken, and you had to call
> > >>> it with two arguments:  an SSLHostConfig and a boolean.
> > >>>
> > >>> In 9.0.83, it seems as though both operations are present, but which
> > one
> > >>> is actually accessible at runtime is non-deterministic.
> > >>>
> > >>> This behavior presents through a direct invoke(...) call and via a JMX
> > >>> Proxy object instantiated through JMX.newMBeanProxy.
> > >>>
> > >>> I have attached a sample file that reproduces the behavior (sometimes,
> > >>> as it is nondeterministic).
> > >>>
> > >>> Is this a bug, or am I simply using the available feature incorrectly?
> > >>>
> > >>> If it is the former, how do I formally report this?  If it is the
> > >>> latter, what is the "correct" way to call this operation from JMX?
> > >>
> > >> I think your attachment was stripped. Can it be posted in-line?
> > >>
> > >> -chris
> > >>
> > >> ---------------------------------------------------------------------
> > >> To unsubscribe, e-mail: users-unsubscr...@tomcat.apache.org
> > >> For additional commands, e-mail: users-h...@tomcat.apache.org
> > >>
> > >>
> > >
> >
> > ---------------------------------------------------------------------
> > To unsubscribe, e-mail: users-unsubscr...@tomcat.apache.org
> > For additional commands, e-mail: users-h...@tomcat.apache.org
> >
> >

---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscr...@tomcat.apache.org
For additional commands, e-mail: users-h...@tomcat.apache.org

Reply via email to