Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

cdata task params #672

Open
phtyson opened this issue Jan 13, 2025 · 3 comments
Open

cdata task params #672

phtyson opened this issue Jan 13, 2025 · 3 comments

Comments

@phtyson
Copy link

phtyson commented Jan 13, 2025

The specific issue I'm having is putting HTML markup in the content parameter of an email task. But I think it could be a more general problem.

The YAWL user manual recommends to simply input cdata-section markup in the parameter Binding field of the editor. The first problem with this is that the editor XQueryEvaluator.maskIndex() method doesn't know about cdata markup, and prevents saving this markup. I tweaked the method to pass cdata-markup through, but then found it still doesn't work with generated content.

<![CDATA[<p>paragraph content here</p>]]>

which works OK for static text, but fails with generated content, like:

<![CDATA[<p>{/Test_email/content/text()}</p>]]>

Because the embedded xquery is passed as literal instead of processed as xquery expression.

When the binding is saved as simply:

<p>{/Test_email/content/text()}</p>

the editor doesn't complain, and the specification can be loaded and run. However, you get MailService runtime error like this:

2025-01-13 20:45:56,815 [ERROR] MailService          :- Catching
org.yawlfoundation.yawl.exceptions.YAWLException: <failure><reason>BAD PROCESS DEFINITION. Data extraction failed schema validation at task starting.
Task [test_email]
XQuery [<content><p>{/Test_email/content/text()}</p></content>]
Document [<Test_email>
  <CCaddress />
  <result />
  <toName>paul</toName>
  <toAddress>[email protected]</toAddress>
  <subject>test</subject>
  <content>Hello, world!</content>
</Test_email>]
Schema for Expected [<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" />]
But received [<test_email>
  <content>
    <p>Hello, world!</p>
  </content>
</test_email>]
Validation error message [Error: 4:13: cvc-type.3.1.2: Element 'content' is a simple type, so it must have no element information item [children].
]</reason></failure>
        at org.yawlfoundation.yawl.engine.interfce.interfaceB.InterfaceBWebsideController.checkOut(InterfaceBWebsideController.java:322) ~[classes/:?]
        at org.yawlfoundation.yawl.engine.interfce.interfaceB.InterfaceBWebsideController.checkOut(InterfaceBWebsideController.java:330) ~[classes/:?]
        at org.yawlfoundation.yawl.mailService.MailService.handleEnabledWorkItemEvent(MailService.java:66) ~[classes/:?]
        at org.yawlfoundation.yawl.engine.interfce.interfaceB.InterfaceB_EnvironmentBasedServer$EventHandler.run(InterfaceB_EnvironmentBasedServer.java:173) ~[classes/:?]
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128) ~[?:?]
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628) ~[?:?]
        at java.lang.Thread.run(Thread.java:829) ~[?:?]
2025-01-13 20:45:56,816 [DEBUG] MailService          :- handleEnabledWorkItemEvent(): completed wid 49

So, it seems impossible to add cdata section with generated content to a task parameter.

The only solution I could find for this problem was to add a isCDATA boolean attribute to the content parameter. In YTask.performDataExtraction(), add the following:

	// if the parameter is CDATA, mark contents as CDATA
	if (inputParam.getAttributes().getBoolean("isCDATA")) {
	    XMLOutputter outputter = new XMLOutputter(Format.getRawFormat());
	    ByteArrayOutputStream bytes = new ByteArrayOutputStream();
	    for (Content c : result.getContent()) {
		try {
		    switch (c.getCType()) {
		    case Element:
			outputter.output((Element) c, bytes);
			break;
		    case Text:
			outputter.output((Text) c, bytes);
			break;
		    case CDATA:
			bytes.write(((CDATA) c).getText().getBytes("UTF-8"));
			break;
		    case Comment:
			outputter.output((Comment) c, bytes);
			break;
		    case DocType:
			outputter.output((DocType) c, bytes);
			break;
		    case EntityRef:
			outputter.output((EntityRef) c, bytes);
			break;
		    case ProcessingInstruction:
			outputter.output((ProcessingInstruction) c, bytes);
			break;
		    default:
			break;
		    }
		} catch (IOException e) {
		    throw new YQueryException("Exception building CDATA element: " + e.getMessage());
		}

	    }
	    CDATA cdata;
	    try {
		cdata = new CDATA(bytes.toString("UTF-8"));
	    } catch (UnsupportedEncodingException e) {
		cdata = new CDATA(bytes.toString());
	    }
	    result.setContent(cdata);
	}

(See attached patch. ytask-iscdata.patch)

If my analysis is correct, please apply the patch to YTask, and add the isCDATA parameter to the standard parameters, and to documentation. Further enhancements could be made to MailService to add isCDATA attribute to content parameter by default. This would advertise the availability of this attribute. Otherwise the spec author will have to know to add this in specification.

If there is another solution that I missed, please advise.

@malcolm-pro
Copy link
Contributor

Looks like it might be treating the <p>...</p> as XML. What happens if you html-escape that text first?

@phtyson
Copy link
Author

phtyson commented Jan 14, 2025

Looks like it might be treating the <p>...</p> as XML. What happens if you html-escape that text first?

The parameter binding editor panel doesn't accept &lt;, etc. input. The editor escapes markup characters in the query when serializing the specification to xml, as in the following mapping element:

            <mapping>
              <expression query="&lt;content&gt;&lt;p&gt;{/Test_email/content/text()}&lt;/p&gt;&lt;/content&gt;" />
              <mapsTo>content</mapsTo>
            </mapping>

I have tried manually editing the mappings in xml specification, but that is tedious and error-prone, and not a good production solution.

@phtyson
Copy link
Author

phtyson commented Jan 15, 2025

The attached test_email workflow specification provides a simple test of a task parameter with cdata content (specifically, the email content parameter). (Change .txt extension to .yawl.)

The email task wraps the input with <p>...</p> markup. If you run this on a current snapshot yawl platform, the mailservice will fail and complain that content can't contain markup, since it is a simple type.

If you apply the ytask-iscdata.patch patch, the workflow will complete normally (because the content parameter has isCDATA=true). The sent email will have an HTML body with proper markup.

If there is a simpler, better way to solve this problem, please advise.

test_email.txt

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants