Regression since 16.0.3: TOD issue create/change-state fails without Wicket application #2852
clark chen opened 21 hours ago

Summary

TOD 4.1.0 cannot create an issue or change an issue state against OneDev 16.0.3 through 16.0.5 when Issue.addMissingFields() is reached. The server returns HTTP 500:

org.apache.wicket.WicketRuntimeException: There is no application attached to current thread

The regression appears to have been introduced by commit 6d1b0475 (OD-2848).

Environment

  • OneDev: 16.0.5
  • Docker image: 1dev/server:16.0.5
  • TOD: 4.1.0
  • Database: PostgreSQL
  • Reverse proxy: Traefik (ruled out; origin and downstream both return the same 500)

The container uses the official image, has no custom OneDev plugins, no duplicate server/Wicket jars, and logs no OOM or database errors.

Reproduction

  1. Configure one or more issue fields with Prompt upon issue open. The affected instance also has valid show conditions/default values depending on another issue field.
  2. Configure TOD for the project.
  3. Run:
tod issue create "TOD create regression" \
  --field 'Issue-Kind=Bug' \
  --field 'Priority=Normal'
  1. Alternatively, run an actual state transition:
tod issue change-state <issue-reference> "In Progress"

Actual result

TOD receives HTTP 500. Server stack for issue creation:

org.apache.wicket.WicketRuntimeException: There is no application attached to current thread
    at org.apache.wicket.Application.get(Application.java:236)
    at org.apache.wicket.Component.getApplication(Component.java:1363)
    at org.apache.wicket.Component.<init>(Component.java:690)
    at io.onedev.server.model.support.issue.field.FieldUtils$1FakeComponent.<init>(FieldUtils.java:227)
    at io.onedev.server.model.support.issue.field.FieldUtils.newContextComponent(FieldUtils.java:250)
    at io.onedev.server.model.support.issue.field.FieldUtils.newBeanComponentContext(FieldUtils.java:254)
    at io.onedev.server.model.support.issue.field.FieldUtils.getFieldValues(FieldUtils.java:111)
    at io.onedev.server.model.Issue.addMissingFields(Issue.java:1101)
    at io.onedev.server.service.impl.DefaultIssueService.open(DefaultIssueService.java:255)
    at io.onedev.server.ai.TodResource.createIssue(TodResource.java:696)

State transition fails through the same field path:

FieldUtils.getFieldValues(FieldUtils.java:111)
Issue.addMissingFields(Issue.java:1101)
DefaultIssueChangeService.changeState(DefaultIssueChangeService.java:397)
TodResource.changeIssueState(TodResource.java:803)

Expected result

TOD should create the issue or change its state successfully. Issue default/show-condition evaluation in a Jersey REST request must not require a Wicket page/application context.

Regression analysis

In OneDev 16.0.2, Issue.addMissingFields() called:

FieldUtils.getFieldValues(null, fieldBean, fieldNames);

and FieldUtils pushed a ComponentContext only when it was non-null.

Commit 6d1b0475 changed this to:

FieldUtils.getFieldValues(fieldBean, fieldNames);

and now unconditionally calls:

ComponentContext.push(
    newBeanComponentContext(new BeanDescriptor(fieldBean.getClass()), fieldBean)
);

newBeanComponentContext() creates a FakeComponent extending MarkupContainer. This works in a Wicket UI request, but TodResource runs in Jersey and has no Wicket application attached to its thread.

The same code is still present in OneDev 16.0.5.

Suggested direction

Please make field default/show-condition evaluation usable in a headless REST context, or avoid constructing a Wicket Component from Issue.addMissingFields() when invoked by TOD/API services. A regression test covering both TodResource.createIssue and TodResource.changeIssueState with prompted/conditional fields would help prevent recurrence.

1/1
Type
Bug
Priority
Normal
Assignee
Affected Versions
16.0.3, 16.0.4, 16.0.5
Labels
No labels
Issue Votes (0)
Watchers (2)
Reference
OD-2852
Please wait...
Connection lost or session expired, reload to recover
Page is in error, reload to recover