I have been Googling and trying to get this to work for hours...The problem is the server is not receiving data as JSON
but as text. This is the POJO
package my.package;
import javax.xml.bind.annotation.XmlRootElement;
@XmlRootElement
public class TestConfig {
private String firmID;
private String traderID;
private String userID;
public TestConfig() {};
...
}
A Javascript client which contains:
function callbackForTest(response) {
console.log("Call to callbackForTest");
if (response.state == "opening" && response.status == 200) {
//push request data
if (connectedEndpoint[0] == null) {
console.log("[DEBUG] Connected endpoint for " + value + "is null!");
//disable button
$(value).attr('disabled','');
$.atmosphere.unsubscribe();
return false;
}
// push ( POST )
connectedEndpoint[0].push(JSON.stringify(
{
operation : "RUN",
firmID : $('#firmID').val(),
userID : $('#userID').val(),
traderID : $('#traderID').val(),
protocol : $('#protocol').val(),
group1 :
}
));
}
}
function subscribeUrl(jobName, call, transport) {
var location = subscribePath + jobName.id;
return subscribeAtmosphere(location, call, transport);
}
function globalCallback(response) {
if (response.state != "messageReceived") {
return;
}
}
function subscribeAtmosphere(location, call, transport) {
var rq = $.atmosphere.subscribe(location, globalCallback, $.atmosphere.request = {
logLevel : 'debug',
transport : transport,
enableProtocol: true,
callback : call,
contentType : 'application/json'
});
return rq;
}
function sendMessage(connectedEndpoint, jobName) {
var phrase = $('#msg-' + jobName).val();
connectedEndpoint.push({data: "message=" + phrase});
}
// Run Test handlers
$("input[name='runButtons']").each(function(index, value){
$(value).click(function(){
//disable button
$(value).attr('disabled','disabled');
// connect (GET)
connectedEndpoint[index] = subscribeUrl(value, callbackForTest, transport);
});
});
I have included the libs shown in this screenshot:
And this is my web.xml (part of it)
com.sun.jersey.api.json.POJOMappingFeature true
The Jersey resource
@Path("/subscribe/{topic}")
@Produces({MediaType.APPLICATION_JSON, "text/html;charset=ISO-8859-1", MediaType.TEXT_PLAIN})
public class Subscriber {
private static final Logger LOG = Logger.getLogger(Subscriber.class);
@PathParam("topic")
private Broadcaster topic;
@GET
public SuspendResponse<String> subscribe() {
LOG.debug("GET - OnSubscribe to topic");
SuspendResponse<String> sr = new SuspendResponse.SuspendResponseBuilder<String>().broadcaster(topic).outputComments(true)
.addListener(new EventsLogger()).build();
return sr;
}
@POST
@Consumes({MediaType.APPLICATION_JSON, MediaType.TEXT_PLAIN, MediaType.TEXT_HTML})
@Broadcast
public Broadcastable publish( TestConfig t) {
LOG.debug("POST");
String s = t.getFirmID();
return new Broadcastable(s, "", topic);
}
I can subscribe OK. When I try to push to the server, I get this exception:
A message body reader for Java class com.mx.sailcertifier.TestConfig, and Java type class com.mx.sailcertifier.TestConfig, and MIME media type text/plain was not found.
Why is it sending plain text if I set the content type to application/json
? What is the correct way to get the Jersey resource to read the JSON?
I finally got this working with two changes:
After looking at the sample here, I added this init-param
to the AtmosphereServlet
in the web.xml
to resolve the text/plain
problem in Tomcat:
<init-param>
<param-name>org.atmosphere.websocket.messageContentType</param-name>
<param-value>application/json</param-value>
</init-param>
I didn't see this anywhere documented in the Atmosphere docs. It would have saved a lot of time had it been, but documentation-wise the API is unfortunately disorganized and lacking.
Also, I needed to use the jersey-bundle jar make sure that everything Jersey related is included, including as the jersey-json.jar
. After that, it worked! Hope this helps someone else who may have been stuck with the same or similar problem.