Classcastexception for CloudEventMessageConverter to AbstractMessageConverter - spring-boot

when using spring cloud stream latest version with cloud events spring sdk
Facing classcastexception in below scenario.
Message has contentType = application/*+avro.
SmartcompositeMessageConverter contains converter list like below -
CloudEventMessageConverter
AvroSchemaRegisteryClientMessageConverter
and some ootb converters.
While converting to message from producer..
SmartcompositeMessageConverter has this line of code for wildcard contentType
((AbstractMessageConverter) converter).getSupportedMimeTypes()
But CloudEventMessageConverter is not an instance of AbstractMessageConverter, hence it throws an exception.
Please guide what should be overridden in this case.
If I create a new CloudEventMessageConverter which extends AbstractMessageConverter, I cann't add headers as only method allowed to override is convertFromInternal which returns just the payload.

Related

Spring RestController endpoint that consumes and produces a String value returning "HTTP Status 415 – Unsupported Media Type"

I'm trying to setup a fairly simple endpoint that takes in String and produces a String. I've simplified it down to:
#RequestMapping(value="/foo",
method = RequestMethod.GET,
consumes = MediaType.TEXT_PLAIN_VALUE,
produces= MediaType.TEXT_PLAIN_VALUE)
public String foo(#RequestBody String data) {
return data;
}
I'm testing with Postman and am just getting "HTTP Status 415 – Unsupported Media Type" back. This app is running on Spring 4.1.3. I copied this endpoint into another project I have in Spring Boot, using my same Postman request (just modified the host), and it works there. So there appears to be some issue with the version of Spring this project uses. As a work-around I created a simple wrapper entity (POJO that only consists of a single String) and changed the endpoint to consume JSON/this POJO. Does anyone know specifically why it doesn't work as above and/or know of a workaround that'll let me send and receive a plain text String with this version of Spring?

SpringBoot get InputStream and OutputStream from websocket

we want to integrate third party library(Eclipse XText LSP) into our SpringBoot webapp.
This library works "interactively" with the user (like chat). XText API requires input and output stream to work. We want to use WebSocket to let users interact with this library smoothly (send/retrieve json messages).
We have a problem with SpringBoot because SpringBoot support for WebSocket doesn't expose input/output streams. We wrote custom TextWebSocketHandler (subclass) but none of it's methods provide access to in/out streams.
We also tried with HandshakeInterceptor (to obtain in/out streams after handshake ) but with no success.
Can we use SpringBoot WebSocket API in this scenario or should we use some lower level (Servlet?) API ?
Regards Daniel
I am not sure if this will fit your architecture or not, but I have achieved this by using Spring Boot's STOMP support and wiring it into a custom org.eclipse.lsp4j.jsonrpc.RemoteEndpoint, rather than using a lower level API.
The approach was inspired by reading through the code provided in org.eclipse.lsp4j.launch.LSPLauncher.
JSON handler
Marhalling and unmarshalling the JSON needs to be done with the API provided with the xtext language server, rather than Jackson (which would be used by the Spring STOMP integration)
Map<String, JsonRpcMethod> supportedMethods = new LinkedHashMap<String, JsonRpcMethod>();
supportedMethods.putAll(ServiceEndpoints.getSupportedMethods(LanguageClient.class));
supportedMethods.putAll(languageServer.supportedMethods());
jsonHandler = new MessageJsonHandler(supportedMethods);
jsonHandler.setMethodProvider(remoteEndpoint);
Response / notifications
Responses and notifications are sent by a message consumer which is passed to the remoteEndpoint when constructed. The message must be marshalled by the jsonHandler so as to prevent Jackson doing it.
remoteEndpoint = new RemoteEndpoint(new MessageConsumer() {
#Override
public void consume(Message message) {
simpMessagingTemplate.convertAndSendToUser('user', '/lang/message',
jsonHandler.serialize(message));
}
}, ServiceEndpoints.toEndpoint(languageServer));
Requests
Requests can be received by using a #MessageMapping method that takes the whole #Payload as a String to avoid Jackson unmarshalling it. You can then unmarshall yourself and pass the message to the remoteEndpoint.
#MessageMapping("/lang/message")
public void incoming(#Payload String message) {
remoteEndpoint.consume(jsonHandler.parseMessage(message));
}
There may be a better way to do this, and I'll watch this question with interest, but this is an approach that I have found to work.

Vulnerability warning with XStreamMarshaller

When using a XStreamMarshaller with spring batch, I get the following message:
Security framework of XStream not initialized, XStream is probably vulnerable.
First try: According to the documentation, I've tried to reset all permissions, but I still have the same message. Besides, I have no security error when parsing XML files... So I think that this code just doen't work. Here's a sample of code:
XStreamMarshaller marshaller = new XStreamMarshaller();
marshaller.getXStream().addPermission(NoTypePermission.NONE);
Second try: I have also tried with the setSupportedClasses method, but it doesn't work either (I still get the vulnerability message and not supported classes are still unmarshelled correctly):
XStreamMarshaller marshaller = new XStreamMarshaller();
marshaller.setSupportedClasses(FooBar.class);
How can I set security permissions with XStreamMarshaller?
Note: according to this thread, the Security Framework was introduced with 1.4.7 and it is still not mandatory.... But it will be mandatory for XStream 1.5.0!
Version of XStream used: 1.4.10
Version of Spring Batch used: 4.0.1
For information, I'm using Spring Boot (but I'm not sure it's relevant here)
Solution for the 'First Try':
The reason why it didn't work is that XStreamMarshaller instantiates a xstream object with afterPropertiesSet without checking if one have already been created, so we can't use getXStream() in a #Bean method. To make this work, we can for example set security config while injecting the marshaller in another bean:
#Configuration
public class JobSecurityConfig {
public JobSecurityConfig(XStreamMarshaller marshaller) {
XStream xstream = marshaller.getXStream();
XStream.setupDefaultSecurity(xstream);
xstream.allowTypes(new Class[]{Bar.class});
}
}
Another solution: extend XSreamMarshaller
You can also extend XStreamMarshaller and override only the customizeXStream() method to set security configuration.
#Override
protected void customizeXStream(XStream xstream) {
XStream.setupDefaultSecurity(xstream);
xstream.allowTypes(new Class[]{Bar.class});
}
Why the 'Second Try' doesn't work:
setSupportedClasses is only used on marshalling!!.. StaxEventItemReader doesn't care about supported classes!
Xstream website have provided details about the Security Framework Security Framework.
below method are provided to set Security permissions
XStream.addPermission(TypePermission);
XStream.allowTypes(Class[]);
XStream.allowTypes(String[]);
XStream.allowTypesByRegExp(String[]);
XStream.allowTypesByRegExp(Pattern[]);
XStream.allowTypesByWildcard(String[]);
XStream.allowTypeHierary(Class);
XStream.denyPermission(TypePermission);
XStream.denyTypes(Class[]);
XStream.denyTypes(String[]);
XStream.denyTypesByRegExp(String[]);
XStream.denyTypesByRegExp(Pattern[]);
XStream.denyTypesByWildcard(String[]);
XStream.denyTypeHierary(Class);
You can also refer this Tutorial
I hope this helps
From the official spring docs:
By default, XStream allows for arbitrary classes to be unmarshalled,
which can lead to unsafe Java serialization effects. As such, it is
not recommended to use the XStreamMarshaller to unmarshal XML from
external sources (i.e. the Web), as this can result in security
vulnerabilities.
You're using Spring's abstraction XStreamMarshaller to interface with the XStream library. By default the library can marshall/unmarshall arbitrary classes (including from external web source).
If you are not doing that (working with classes from external web sources) you can simply ignore the message.
If you want to remove the message follow what's recommended in Spring's official doc (linked above) and XStream website (security config example).
It boils down to setting up supported classes to make sure only the registered classes are eligible for unmarshalling.
This property is empty by default, which means - support all classes - hence the warning message you're getting.

Output is not coming in JSON format when NoHandlerFoundException coming

I am using spring 4.X to develop rest api using annotation configuration. I have added servlet.setThrowExceptionIfNoHandlerFound(true) to send NoHandlerFoundException. Created one GlobalExceptionHandler to handle all exception. My question is if NoHandlerFoundException occurs than output is not coming in JSON Format. Do i need to add anything in my servlet configuration

Custom Logging Interceptor is not getting triggered

We are developing a RESTFUL services in spring framework and the log framework we are using is apache CXF.
We get the request in the form of JSON from the consumers of our services and we need to mask some of the contents of JSON before printing in the log files.
We are trying to have a custom interceptor to intercept the logger messages but the request never reaches the custom interceptor class. Can you please provide your thoughts to resolve the issue.
Below are the additional details :
public class CustomLogInterceptor extends LoggingInInterceptor {
public String transform(String originalLogString) {
// Custom logic will be here to mask the originalLogString
}
}
spring context XML changes:
The CustomLogInterceptor class is included in the spring context XML file.
Any help is greatly appreciated!

Resources