I'm working on a RESTful Web-service using Jersey v1.9.1. Some methods return JSON. When I want to Debug my application I start within a grizzly server, otherwise for production I build a war file and place it in a TomCat v7 installation. My projects are all Maven2 projects.
Now, I noticed that for a method that returns List<CustomObj>, where CustomObj has appropriate JAXB annotations, i.e. #XmlRootElement(name="CustomObj"), and getter/setters for all relevant members:
Using grizzly, I get something like {"CustomObj":[{<fields-of-customObj>},{<fields-of-customObj>},{<fields-of-customObj>}]} (when the list has 3 elements). Parsing this with GSON works fine.
Using TomCat, however, I get this: [{<fields-of-customObj>},{<fields-of-customObj>},{<fields-of-customObj>}] -> so as you can see, the "root" is missing somehow
I have the impression that the jersey-json module (which I included into my Maven2 dependencies) are not used at all in TomCat, even though they should be used (they are used in Grizzly for sure). Also, creating my own #Provider for a ContextResolver<JAXBContext> as described here only works in grizzly, in TomCat the getContext() method will never be called.
Is there anything I need to consider with TomCat?
Cheers!
Related
I started using SpringBoot and like it a lot. I see that #RestController automatically serializes POJOs to json. I like that functioonality, but would like to use it outside of a web server context.
Basically I'd like to have all the part of SpringBoot until the point where the response is in JSON format, but then I don't want to deliver it via a web server, but rather my own implementation.
Is there an interface I have to implement in order to get SpringBoot to accept non-web-requests and return non-web-responses.
An example to make clear what I want:
Right now I can access localhost:8080/hello and SpringBoot will return "world".
Is there a way to make this work on console. E.g. I enter "hello" on console and press enter and I get "world" delivered to console by SpringBoot.
So instead of a web interface via tomcat I'd like to implement a console interface but with the same SpringBoot functionality.
UPDATE: The console application was probably not the right example. I am looking for a more general approach. So let's say instead of a console interface I want an Arduino to be able to send "hello" to SpringBoot via a serial bluetooth connection and SpringBoot should return "world" on that same bluetooth serial connection. My question is, whether there is an interface I need to implement in order to tell SpringBoot how to accept REST requests and how to send responses. And I don't want to focus on a particular implementation (like console or BT serial), but instead, once the SpringBoot application is created, I'd like to just replace the tomcat web interface by a BT serial interface or a console interface or any other interface I want to implement, but keep all of the logic (Controllers, Models etc).
Thanks.
Sure! You can create a console application.
You will need to create a class that implements ConsoleRunner. Please find a tutorial here:
https://www.baeldung.com/spring-boot-console-app
If it is the JSON de/serialization that interests you.
You can use Jackson's ObjectMapper .
You don't need the whole spring-boot web stuff.
You can ommit the starter-web dependency and use CommandLineRunner and jackson to have a console application that de/serializes your responses/requests to json.
Im migrating my code to a core application.
So far so good. i got it all running, but there is one problem.
I had a ui (with razor) and using the CatchAllHandlers. And for the api i used HandlerFactoryPath to prefix the urls.
Now i have 2 problems:
It seems CatchAllHandlers isn't used?
Route is only processed if route starts with HandlerFactoryPath?
The second issue is fixable but how would i go around the first one?
Do i make my own middle-ware or does servicestack support other ways of doing this?
CatchAllHandlers are executed in .NET Core, it's also what ServiceStack's new MVC RazorFormat uses to process Content Pages.
Specifying a HandlerFactoryPath, e.g:
SetConfig(new HostConfig {
HandlerFactoryPath = "api"
});
Tells ServiceStack that you only want to listen to requests from the /api path info. All other requests are passed through ServiceStack who calls the next module in .NET Core pipeline as per .NET Core's convention when it's not configured to handle a route.
Not sure if it's relevant to your solution but in ServiceStack .NET Core you can register a ServiceStack Handler in .NET Core module pipeline so you could for instance return a /default.cshtml Content Razor Page for each request that's not handled by ServiceStack, by registering it after ServiceStack:
app.UseServiceStack(new AppHost());
app.Use(new RazorHandler("/default"));
I try to marshall a List<List<String>> to CSV with a route like:
from("direct:ListToCsv").marshal(csvDataFormat_list).convertBodyTo(String.class).to("mock:ListToCsv");
In CsvMarshaller.getRecordValues, there's a "convert to Map" called there that doesn't have the same behavior if camel Spring boot is used (maybe just in camel spring, don't know).
If SpringTypeConverter is enabled (wich is automatic in spring boot) the method "convertTo" throw an ConverterNotFoundException and the route stop there.
Before spring-boot (or if I remove it), the conversion to map in the CsvMarshaller return null and the conversion is executed as list and it works.
So, question... I think it's a bug or do I miss something with the use of Spring for fallback type converter (I didn't use it before)?
Thanks!
[UPDATE]
It seems to be fixed in the next version of camel-csv (2.16.X)
I'm implementing a REST service using Camel's cxfrs component. Various examples I've seen around the inets say I can get the service to return a JSON serialization of the object in question using a cxf:providers tag, like so
<cxf:rsServer id="rsServer" address="${CXFserver}${service}" serviceClass="org.trinityhealth.esb.PersonService"
loggingFeatureEnabled="true" loggingSizeLimit="20">
<cxf:providers>
<bean id="jsonHandler" class="com.fasterxml.jackson.jaxrs.json.JacksonJsonProvider" />
</cxf:providers>
</cxf:rsServer>
This compiles and deploys just fine. But no matter what variant of this config I try, the service responds with "No message body writer has been found for response class Person". The Person class has a "#XmlRootElement(name = "Person")" annotation in it, which I guess is great if I wanted XML produced. But I don't - I want JSON. Jackson has a ton of annotations, do I need to add one to the Person class to get my service to realize I want the class serialized by the Jackson writer?
I don't know Camel that well, but typically Jackson does NOT require root annotation, unlike JAXB (partly since JSON structure does not require name for root type), so it seems unlikely you would such annotation.
I am guessing that rather the registration does not succeed for some reason.
My understanding regarding TomEE (or any Java EE 6 container) is all that i just need to deploy a JAX-RS based application with correct service class annotated.
#Path("/hr")
public class HelloRest {
#GET
#Produces(MediaType.APPLICATION_JSON)
public String getClichedMessage() {
return "Hello World";
}
}
The TomEE container SHOULD take care of converting the "hello world" to proper json format {"hello world"}
I was wondering why TomEE is not converting it to JSON format. Please note I've not used any spring configuration for CXF as I expect this to work with/without CXF configuration.
The certified Web Profile implementation of TomEE does not implement JAX-RS, since JAX-RS is not part of the Web Profile in Java EE 6 (it is in Java EE 7 though).
However, since it appeared that there actually IS very useful stuff in Java EE 6 that goes beyond the Web Profile, TomEE has 2 extra distributions that contains some of this extra stuff.
On the download page you'll find the "JAX-RS" and "Plus" distributions that both contain JAX-RS. With those (or any full profile Java EE AS) you indeed don't need any configuration.
Produces/Consumes doesnt mean convert, it is mainly http headers. String in json is a...string. depend of course of your body writer.