xuxueli/xxl-job · error · IllegalArgumentException

>>>>>>>>>>> xxl-glue, loadNewInstance error, cannot convert

Error message

>>>>>>>>>>> xxl-glue, loadNewInstance error, cannot convert from instance[{}] to IJobHandler

What it means

Thrown by GlueFactory.loadNewInstance as IllegalArgumentException when a glue source class was compiled and instantiated but does not implement IJobHandler. Glue jobs must be executable handlers, so the loaded type is rejected after instantiation.

Source

Thrown at xxl-job-core/src/main/java/com/xxl/job/core/glue/GlueFactory.java:61

	private final GroovyClassLoader groovyClassLoader = new GroovyClassLoader();
	private final ConcurrentMap<String, Class<?>> CLASS_CACHE = new ConcurrentHashMap<>();

	/**
	 * load new instance, prototype
	 *
	 * @param codeSource  code source
	 * @return IJobHandler
	 */
	public IJobHandler loadNewInstance(String codeSource) throws Exception{
		if (StringTool.isNotBlank(codeSource)) {
			Class<?> clazz = getCodeSourceClass(codeSource);
			if (clazz != null) {
				Object instance = clazz.newInstance();
                if (instance instanceof IJobHandler) {
                    this.injectService(instance);
                    return (IJobHandler) instance;
                } else {
                    throw new IllegalArgumentException(">>>>>>>>>>> xxl-glue, loadNewInstance error, "
                            + "cannot convert from instance[" + instance.getClass() + "] to IJobHandler");
                }
            }
		}
		throw new IllegalArgumentException(">>>>>>>>>>> xxl-glue, loadNewInstance error, instance is null");
	}
	private Class<?> getCodeSourceClass(String codeSource){
		try {
			// md5
			byte[] md5 = MessageDigest.getInstance("MD5").digest(codeSource.getBytes());
			String md5Str = new BigInteger(1, md5).toString(16);

			Class<?> clazz = CLASS_CACHE.get(md5Str);
			if(clazz == null){
				clazz = groovyClassLoader.parseClass(codeSource);
				CLASS_CACHE.putIfAbsent(md5Str, clazz);
			}
			return clazz;

View on GitHub (pinned to e74c784f68)

Solutions

  1. Make the glue class implement IJobHandler and provide the required execute method.
  2. Ensure the script imports com.xxl.job.core.handler.IJobHandler (and ReturnT) from the matching core version.
  3. Re-save the corrected glue source so GlueFactory reloads a fresh class.

Example fix

// before - plain class, no handler interface
class MyJob {
    def run(){ ... }
}
// after
class MyJob implements com.xxl.job.core.handler.IJobHandler {
    @Override
    public com.xxl.job.core.router.model.ReturnT<String> execute(String param){ ... }
}
Defensive patterns

Strategy: type-guard

Validate before calling

Class<?> clazz = getCodeSourceClass(codeSource);
if (clazz == null || !IJobHandler.class.isAssignableFrom(clazz)) {
    throw new IllegalArgumentException("glue class must implement IJobHandler: " + clazz);
}

Type guard

boolean isHandler(Class<?> c) {
    return c != null && com.xxl.job.core.handler.IJobHandler.class.isAssignableFrom(c);
}

Try / catch

try {
    IJobHandler h = glueFactory.loadNewInstance(codeSource);
} catch (IllegalArgumentException e) {
    log.error("glue load failed: {}", e.getMessage());
}

Prevention

When it happens

Trigger: Saving/running a glue script whose class (or its hierarchy) does not implement com.xxl.job.core.handler.IJobHandler; the class loads via the Groovy classloader, instantiates, then fails the instanceof check.

Common situations: Edited a glue script and removed 'implements IJobHandler'; pasted a plain Groovy class; renamed the execute contract; glue code compiled against an incompatible xxl-job-core version.

Related errors


AI-assisted analysis of xuxueli/xxl-job@e74c784f68 (2026-08-14). Data as JSON: /api/errors/6455d9101ba80c57. Report an issue: GitHub.