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

Jakarta Faces 4.0 websocket jakarta.faces.push.PushContext fails to serialize objects in certain cases #26854

Open
hrsto opened this issue Nov 7, 2023 · 6 comments
Assignees
Labels
in:Web Components Needs member attention release bug This bug is present in a released version of Open Liberty team:Sirius

Comments

@hrsto
Copy link

hrsto commented Nov 7, 2023

Describe the bug
jakarta.faces.push.PushContext#send(Object) fails in these cases:

  1. When it is given a collection of java record objects. The javascript websocket message handler will return an array of empty json objects. The array size is equal to the size java record given to send(Object)
  2. When it is given a class generated by apache avro, regardless if it's just one class or collection of such classes. Nothing is being sent back to javascript handler.

Steps to Reproduce
Follow javadoc of jakarta.faces.push.Push to setup basic code.

  1. Add to some Faces page <f:websocket channel="myStream" onmessage="myStreamListener" />
  2. Add the javascript listener somewhere:
function myStreamListener(message, channel, event) {
     console.log(message);
 }
  1. In a java @Session CDI bean:
@Inject @Push PushContext myStream;

public void pushData(List<SomeRecord> data) {
	// SomeRecord can be a java record or apache avro generated class (via its maven plugin)
	// Fixed by changing it to a POJO
	var messagesSendStatuses = myStream.send(data);
}

Expected behavior
Should receive a properly serialized object. Should support java record classes.

Diagnostic information:

  • OpenLiberty Version: 21.0.0.10
  • Affected feature(s): faces-4.0
  • Java Version:
openjdk 17.0.2 2022-01-18
OpenJDK Runtime Environment (build 17.0.2+8-86)
OpenJDK 64-Bit Server VM (build 17.0.2+8-86, mixed mode, sharing)
  • server.xml configuration:
<?xml version="1.0" encoding="UTF-8"?>
   <featureManager>
   	<feature>localConnector-1.0</feature>
   	<feature>faces-4.0</feature>
   	<feature>cdi-4.0</feature>
   	<feature>websocket-2.1</feature>
   	<feature>expressionLanguage-5.0</feature>
   	<feature>servlet-6.0</feature>
       <feature>restfulWS-3.1</feature>
       <!-- <feature>sessionCache-1.0</feature> -->
       <feature>appSecurity-5.0</feature>
       <feature>mpConfig-3.0</feature>
   </featureManager>
   <httpEndpoint id="defaultHttpEndpoint" httpPort="8080" />
   <applicationMonitor updateTrigger="polled"/>
   <ssl id="defaultSSLConfig" trustDefaultCerts="true" />

   <mpMetrics authentication="false" />

   <basicRegistry></basicRegistry>
</server>
  • $WLP_OUTPUT_DIR/messages.log: no error messages, or any message at all is being outputted at the time of sending websocket messages.

Additional context
Above issues disappear as soon as i start using POJOs.

@hrsto hrsto added the release bug This bug is present in a released version of Open Liberty label Nov 7, 2023
@volosied
Copy link
Member

volosied commented Nov 7, 2023

Hi, thanks for bringing this to our attention. If you have a WAR file you could also provide, that would be great.

I'll investigate and see what I can do. Thanks!

@volosied
Copy link
Member

volosied commented Nov 7, 2023

I created an issue here: https://issues.apache.org/jira/browse/MYFACES-4637.

I'm not too sure how much I can help out with Records since they are a Java 14+ feature, and faces-4.0 is built with Java 11. The problem is within our Json encoding logic. We check object type to encode it properly, but since it's a Record, nothing matches. It's ultimately treated as a bean, and the handing is therefore incorrect -- hence empty json data is returned.

The only workaround I can provide is to call toString() on the collection, which works in my testing. Nevertheless, I'll collaborate with the open source community via the JIRA above. Perhaps there may be something else we can do here.

I'm curious how the Apache Arvo classes are generated? I would expect classes to work? Can you provide an example?

@hrsto
Copy link
Author

hrsto commented Nov 8, 2023

Providing minimal example on github: https://github.com/hrsto/jakarta-faces-bug-report

Run it locally via liberty maven plugin mvn liberty:dev.

Avro class generated with avro plugin: mvn avro:schema.

Open page http://localhost:8080/bug/ and click Send push message via websocket to trigger the 3 cases - java record, avro, POJO.

@volosied
Copy link
Member

Thanks for providing an app. I see that in the avro case, the JSON encoding fails on the line value = property.getReadMethod().invoke(bean);

property.getReadMethod() returns public org.apache.avro.Schema org.apache.avro.Schema.getElementType()

The issue is that getElementType throws an exception:

org.apache.avro.AvroRuntimeException: Not an array: {"type":"record","name":"SomeSample","namespace":"com.bug.report","fields":[{"name":"iso","type":"string"},{"name":"continent","type":["null","string"],"default":null},{"name":"country","type":"string"}],"connect.doc":"Sample for bug report.","connect.version":1,"connect.name":"SomeSample"}

MyFaces' JSON.java class looks at all the properties of the object it's encoding and tries to call all the read methods.

As for why the Schema class is getting encoded -- Your object SomeSample contains the mention getSchema, so the JSON encoder tries to encode the Schema$RecordSchema, too. That's where it encounters the getElementType method.

I'm not sure what exactly could be done here in MyFaces. You might need to use toString here as well.

SomeSample#toString returns:
[{"iso": "AVRO iso", "continent": "AVRO continent", "country": "AVRO country"}]

@volosied
Copy link
Member

volosied commented Feb 9, 2024

Jakarta Faces 4.1 (EE11) will be built with Java 17 -- this means we can support Java Records.

We only have the 4.1-RC1 out right now, and we haven't added record encoding just yet. I'll aim to have this in 4.1.0-RC2 (or whichever release is next). When we beta faces, you you be able to send records.

@volosied
Copy link
Member

volosied commented May 9, 2024

I've fixed the record encoding in MyFaces 4.1. It will be in the next release ( RC3 currently).

As for avro encoding, I'm not sure what I can do as I mentioned before. We could have a exception for Avro code, but that means we'd need to use it as a dependency, and that's not ideal.

I'll keep this issue open until we pull the record into Liberty. Note that the faces-4.1 is still in development - we hope to get it into beta soon. Thanks!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
in:Web Components Needs member attention release bug This bug is present in a released version of Open Liberty team:Sirius
Projects
Status: General Issues
Web Tier Team
  
General Issues
Development

No branches or pull requests

4 participants