Skip to content

postBootCommands with arguments throws UnsupportedOperationException #36

@jcputney

Description

@jcputney

Summary

<property name="postBootCommands"> in arquillian.xml triggers UnsupportedOperationException whenever a command line has at least one argument. The connector parses each command into an immutable list and then mutates it.

Reproduces 100% with ee.omnifish.arquillian:arquillian-glassfish-server-managed:2.1.3 on Eclipse GlassFish 8.0.1 (JDK 21).

Reproducer

arquillian.xml:

<container qualifier="glassfish-managed">
  <configuration> 
    <property name="glassFishHome">/path/to/glassfish8</property> 
    <property name="domain">domain1</property> 
    <property name="postBootCommands"> 
      create-system-properties foo=bar 
    </property> 
  </configuration> 
</container> 

Any test that boots this container fails with:

java.lang.UnsupportedOperationException
    at java.base/java.util.AbstractList.add(AbstractList.java:155) 
    at java.base/java.util.AbstractList.add(AbstractList.java:113) 
    at ee.omnifish.arquillian.container.glassfish.managed.GlassFishServerControl.executeAdminDomainCommand(GlassFishServerControl.java:315) 
    at ee.omnifish.arquillian.container.glassfish.managed.GlassFishServerControl.start(GlassFishServerControl.java:162) 

It also fires at @AfterSuite teardown when keepServerRunning=false.

Root cause (from disassembly of 2.1.3)

In GlassFishServerControl.start(), the post-boot loop builds a per-command arg list with either Arrays.asList(Arrays.copyOfRange(tokens, 1, end)) (when the command has args) or List.of() (no args). Both are immutable.

That list is then passed to executeAdminDomainCommand(...), whose body does:

// args = parameter #3 (the immutable list above) 
if (config.getDomain() != null) { 
    args.add(config.getDomain());   // ← UnsupportedOperationException 
} 
executeAdminCommand(..., args, ...); 

The contract violation is executeAdminDomainCommand mutating its caller's list. The cleanest fix is for that method to defensively copy:

private void executeAdminDomainCommand(String cmd, String op, List<String> args, ProcessOutputConsumer out)
        throws LifecycleException { 
    List<String> mutable = new ArrayList<>(args); 
    if (config.getDomain() != null) { 
        mutable.add(config.getDomain()); 
    } 
    executeAdminCommand(cmd, op, mutable, List.of(), out);
} 

This also fixes the corresponding call from stop() / stopContainer() if those use the same path with an immutable arg list.

Workaround

Until this is fixed, consumers must avoid postBootCommands entirely. Editing domain.xml directly via Maven or asadmin running against an already-started server are the available alternatives.

Versions

  • ee.omnifish.arquillian:arquillian-glassfish-server-managed 2.1.3
  • Eclipse GlassFish 8.0.1 (JDK21 distribution)
  • JDK 21.0.5 (Corretto)
  • Maven 3.9.15
  • Arquillian core 1.10.0.Final

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions