I've recently joined a project where I'm supposed to change the web services from Axis1.2 to REST. The project is in development for 10 years and many people have worked on it, so unfortunately I can't tell why something is done, only that it is done.
I am using Jersey and though I have worked through many tutorials, it still doesn't work.
This is my server code:
#Path("/positionfacade")
#Consumes(MediaType.APPLICATION_XML)
public class PositionFacadeRest implements PositionFacadeInterface {
#POST
#Path("/{sessionId}/{type}/{mapIdentifier}/{positionX}/{positionY}/{positionZ}/{character}/{identifier}/{displayName}/{fixed}/{attributes}/{lastObservedTime}/{sensorData}/{coordinates}")
#Consumes(MediaType.APPLICATION_XML)
public void createOrUpdatePositionRest(
#PathParam("sessionId") long sessionId,
#PathParam("type") String type,
#PathParam("mapIdentifier") String mapIdentifier,
#PathParam("positionX") Integer positionX,
#PathParam("positionY") Integer positionY,
#PathParam("positionZ") Integer positionZ,
#PathParam("character") SignalCharacterDTO character,
#PathParam("identifier") String identifier,
#PathParam("displayName") String displayName,
#PathParam("fixed") Boolean fixed,
#PathParam("attributes") AttributesDTO attributes,
#PathParam("lastObservedTime") long lastObservedTime,
#PathParam("sensorData") SensorDTO[] sensorData,
#PathParam("coordinates") CoordinateDTO[] coordinates)
throws SessionException, MapException {
...
}
}
My client code:
import com.sun.jersey.api.client.Client;
import com.sun.jersey.api.client.WebResource;
...
Client restclient = Client.create();
WebResource resource = restclient.resource("http://"+sci.getHostName()+":"+new Integer(sci.getPort()).toString()+"/application/rest/positionfacade/"+
sessionIds.get(sci)+"/"+
node.getType()+"/"+
controller.getCurrentMap().getIdentifier()+"/"+
node.getX()+"/"+
node.getY()+"/"+
node.getZ()+"/"+
signalCharacter_+"/"+
node.getIdentifier()+"/"+
node.getDisplayName()+"/"+
null+"/"+
null+"/"+
lastObservedTime_+"/"+
null+"/"+
null
);
resource.post();
The web.xml:
<servlet>
<servlet-name>rest</servlet-name>
<servlet-class>
com.sun.jersey.spi.container.servlet.ServletContainer
</servlet-class>
<init-param>
<param-name>com.sun.jersey.config.property.packages</param-name>
<param-value>net.sf.application.server.facade</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>rest</servlet-name>
<url-pattern>/rest/*</url-pattern>
</servlet-mapping>
And the error Message:
Exception in thread "Thread-64" com.sun.jersey.api.client.UniformInterfaceException: POST http://localhost:8080/application/rest/positionfacade/121/CLIENT/eca723a4-bd53-405e-893b-6ff8365d58b9/0/0/0/net.sf.application.server.dto.SignalCharacterDTO#229509bb/1/1/null/null/-1/null/null returned a response status of 404 Not Found
The application is running on Tomcat7 and is in webapps/application
Many many thanks for your help in advance. :-)
Related
I have an api that needs to implement security.
But the filter is not invoked. my call pass directly to the endpoint...
My Secure interface
#NameBinding
#Retention(RetentionPolicy.RUNTIME)
#Target({ElementType.TYPE,ElementType.METHOD})
public #interface Seguro {}
My Filter
#Seguro
#Provider
#Priority(Priorities.AUTHENTICATION)
public class FiltroAutenticacao implements ContainerRequestFilter {
#Override
public void filter(ContainerRequestContext requestContext) throws IOException {
String authorizationHeader = requestContext.getHeaderString(HttpHeaders.AUTHORIZATION);
if (authorizationHeader == null || !authorizationHeader.startsWith("Bearer ")) {
throw new NotAuthorizedException("Authorization header precisa ser provido");
}
String token = authorizationHeader.substring("Bearer".length()).trim();
try {
...
} catch (Exception e) {
...
}
}
}
My method that needs to be authenticated.
#Seguro
#GET
#Path("/metodo-teste")
#Produces("application/json")
public Response medotoTeste(#QueryParam("codigo") String codigo){
ModeloTesteTO to = new ModeloTesteTO("codigo enviado foi " + codigo);
return Response.ok(to, MediaType.APPLICATION_JSON).build();
}
Do I need to implement anything else?
My web.xml
<servlet>
<servlet-name>Jersey REST Service</servlet-name>
<servlet-class>com.sun.jersey.spi.container.servlet.ServletContainer</servlet-class>
<init-param>
<param-name>com.sun.jersey.config.property.resourceConfigClass</param-name>
<param-value>com.sun.jersey.api.core.PackagesResourceConfig</param-value>
</init-param>
<init-param>
<param-name>com.sun.jersey.config.property.packages</param-name>
<param-value>br.gov.es.dataci.aprender</param-value>
</init-param>
<init-param>
<param-name>com.sun.jersey.spi.container.ContainerRequestFilters</param-name>
<param-value>br.gov.es.dataci.aprender.seguranca.FiltroAutenticacao</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>Jersey REST Service</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping>
I am using Jersey 1.17 and glassfish 4
I discovered the problem, following Paul's suggestion of trying to publish the application with Jersey 2 on the glassfish, I discovered incompatibility in glassfish version. Glassfish 4.0 does not support jersey 2, the 4.1.2 version yes. I migrated the server and solved the problem.
I am trying to use Jersey to provide a simple web service for my struts application.
When I call the client action I get the following error
com.sun.jersey.api.client.UniformInterfaceException
Message: GET http://localhost:8080/shumer/rest/employee/get returned a response status of 404
servlet declaration in web.xml
<servlet>
<servlet-name>JAX-RS Servlet</servlet-name>
<servlet-class>com.sun.jersey.spi.spring.container.servlet.SpringServlet</servlet-class>
<init-param>
<param-name>spring.autowire</param-name>
<param-value>byName</param-value>
</init-param>
<load-on-startup>3</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>JAX-RS Servlet</servlet-name>
<url-pattern>/rest/*</url-pattern>
</servlet-mapping>
Server resource
#Path("employee")
public class EmployeeResource {
#Autowired
EmpDao empDao;
#GET
#Produces(MediaType.APPLICATION_JSON)
public List<Employee> get(#QueryParam("empCode") String empCode) throws Exception {
EmpCriteria criteria = new EmpCriteria();
criteria.setEmpCode(empCode);
return empDao.searchByCondition(criteria);
}
}
Client action
public class EmployeeClientTestAction extends Action {
#Override
public ActionForward execute(ActionMapping mapping, ActionForm form, HttpServletRequest request,
HttpServletResponse response) throws Exception {
Client client = Client.create();
WebResource resource = client.resource("http://localhost:8080/shumer/rest/employee/get");
String employees= resource.accept(MediaType.APPLICATION_JSON)
.get(String.class);
System.out.println(employees);
request.setAttribute("employees", employees);
return mapping.findForward("successful");
}
}
I have tried this with and without the /get and the end of the resource url, and with and without a leading / in the EmployeeResource #Path annotation. My guess is that there is somewhere I have to declare where my resources are lcoated at in order for the Jersey servlet to handle them, but I can't figure it out. A point in the right direction would be much appreciated.
EDIT
I have added the following init-param to the servlet element and it is still not working (this package is where my resource class is)
<init-param>
<param-name>com.sun.jersey.config.property.packages</param-name>
<param-value>shumer.rest.resource</param-value>
</init-param>
in get method write #Path("/get")
I have a problem (similar to this one ?) which started when I switched jersey (2.19) from a descriptor-less deployment via #ApplicationPath to a servlet 2.x filter in an existing JAX-RS web application.
As soon as I finished SSE didn't work anymore. As I was using the SSEBroadcaster at the time I built a simpler test method because I didn't get any exceptions with the broadcaster.
Finally the exception popped up:
Severe: java.lang.NullPointerException
at org.apache.catalina.connector.OutputBuffer.writeBytes(OutputBuffer.java:350)
at org.apache.catalina.connector.OutputBuffer.write(OutputBuffer.java:342)
at org.apache.catalina.connector.CoyoteOutputStream.write(CoyoteOutputStream.java:161)
at org.apache.catalina.connector.CoyoteOutputStream.write(CoyoteOutputStream.java:150)
at org.glassfish.jersey.servlet.internal.ResponseWriter$NonCloseableOutputStreamWrapper.write(ResponseWriter.java:293)
at org.glassfish.jersey.message.internal.CommittingOutputStream.write(CommittingOutputStream.java:214)
at org.glassfish.jersey.media.sse.OutboundEventWriter.writeTo(OutboundEventWriter.java:100)
at org.glassfish.jersey.media.sse.OutboundEventWriter.writeTo(OutboundEventWriter.java:63)
at org.glassfish.jersey.message.internal.WriterInterceptorExecutor$TerminalWriterInterceptor.invokeWriteTo(WriterInterceptorExecutor.java:263)
at org.glassfish.jersey.message.internal.WriterInterceptorExecutor$TerminalWriterInterceptor.aroundWriteTo(WriterInterceptorExecutor.java:250)
at org.glassfish.jersey.message.internal.WriterInterceptorExecutor.proceed(WriterInterceptorExecutor.java:162)
at org.glassfish.jersey.message.internal.MessageBodyFactory.writeTo(MessageBodyFactory.java:1154)
at org.glassfish.jersey.server.ChunkedOutput$1.call(ChunkedOutput.java:219)
at org.glassfish.jersey.server.ChunkedOutput$1.call(ChunkedOutput.java:190)
at org.glassfish.jersey.internal.Errors.process(Errors.java:315)
at org.glassfish.jersey.internal.Errors.process(Errors.java:242)
at org.glassfish.jersey.process.internal.RequestScope.runInScope(RequestScope.java:347)
at org.glassfish.jersey.server.ChunkedOutput.flushQueue(ChunkedOutput.java:190)
at org.glassfish.jersey.server.ChunkedOutput.write(ChunkedOutput.java:180)
at ch.company.app.controller.MyController$1.run(MyController.java:62)
at java.lang.Thread.run(Thread.java:745)
The code I used is a variant of the official Jersey documentation found here:
#RequestScoped
#Path("api")
public class MyController {
private final static Logger LOGGER = Logger.getLogger(MyController.class.getName());
#GET
#Path("test")
#Produces(SseFeature.SERVER_SENT_EVENTS)
public EventOutput getServerSentEvents() {
final EventOutput eventOutput = new EventOutput();
new Thread(new Runnable() {
#Override
public void run() {
try {
int counter = 0;
while (!eventOutput.isClosed()) {
LOGGER.log(Level.INFO, "Eventoutput closed?: " + eventOutput.isClosed());
final OutboundEvent.Builder eventBuilder = new OutboundEvent.Builder();
eventBuilder.name("message-to-client");
eventBuilder.id("c" + counter);
eventBuilder.comment("this is a test comment");
eventBuilder.data(String.class, "Hello world " + counter + "!");
counter++;
final OutboundEvent event = eventBuilder.build();
eventOutput.write(event);
//Thread.sleep(Integer.toUnsignedLong(5000));
}
} catch (IOException e) {
throw new RuntimeException("Error when writing the event.", e);
//} catch (InterruptedException ex) {
// Logger.getLogger(MyController.class.getName()).log(Level.SEVERE, null, ex);
} finally {
try {
eventOutput.close();
} catch (IOException ioClose) {
throw new RuntimeException("Error when closing the event output.", ioClose);
}
}
}
}).start();
return eventOutput;
}
}
If I only use eventBuilder.data(...) and not use name(), id(), comment() the exception (as suggested here) would slightly change to this:
Severe: java.lang.NullPointerException
at org.apache.catalina.connector.OutputBuffer.writeBytes(OutputBuffer.java:350)
at org.apache.catalina.connector.OutputBuffer.write(OutputBuffer.java:342)
at org.apache.catalina.connector.CoyoteOutputStream.write(CoyoteOutputStream.java:161)
at org.apache.catalina.connector.CoyoteOutputStream.write(CoyoteOutputStream.java:150)
at org.glassfish.jersey.servlet.internal.ResponseWriter$NonCloseableOutputStreamWrapper.write(ResponseWriter.java:293)
at org.glassfish.jersey.message.internal.CommittingOutputStream.write(CommittingOutputStream.java:214)
at org.glassfish.jersey.media.sse.OutboundEventWriter$1.write(OutboundEventWriter.java:141)
at java.io.OutputStream.write(OutputStream.java:116)
at sun.nio.cs.StreamEncoder.writeBytes(StreamEncoder.java:221)
at sun.nio.cs.StreamEncoder.implFlushBuffer(StreamEncoder.java:291)
at sun.nio.cs.StreamEncoder.implFlush(StreamEncoder.java:295)
at sun.nio.cs.StreamEncoder.flush(StreamEncoder.java:141)
at java.io.OutputStreamWriter.flush(OutputStreamWriter.java:229)
at java.io.BufferedWriter.flush(BufferedWriter.java:254)
at org.glassfish.jersey.message.internal.ReaderWriter.writeToAsString(ReaderWriter.java:192)
at org.glassfish.jersey.message.internal.AbstractMessageReaderWriterProvider.writeToAsString(AbstractMessageReaderWriterProvider.java:129)
at org.glassfish.jersey.message.internal.StringMessageProvider.writeTo(StringMessageProvider.java:99)
at org.glassfish.jersey.message.internal.StringMessageProvider.writeTo(StringMessageProvider.java:59)
at org.glassfish.jersey.media.sse.OutboundEventWriter.writeTo(OutboundEventWriter.java:127)
at org.glassfish.jersey.media.sse.OutboundEventWriter.writeTo(OutboundEventWriter.java:63)
at org.glassfish.jersey.message.internal.WriterInterceptorExecutor$TerminalWriterInterceptor.invokeWriteTo(WriterInterceptorExecutor.java:263)
at org.glassfish.jersey.message.internal.WriterInterceptorExecutor$TerminalWriterInterceptor.aroundWriteTo(WriterInterceptorExecutor.java:250)
at org.glassfish.jersey.message.internal.WriterInterceptorExecutor.proceed(WriterInterceptorExecutor.java:162)
at org.glassfish.jersey.message.internal.MessageBodyFactory.writeTo(MessageBodyFactory.java:1154)
at org.glassfish.jersey.server.ChunkedOutput$1.call(ChunkedOutput.java:219)
at org.glassfish.jersey.server.ChunkedOutput$1.call(ChunkedOutput.java:190)
at org.glassfish.jersey.internal.Errors.process(Errors.java:315)
at org.glassfish.jersey.internal.Errors.process(Errors.java:242)
at org.glassfish.jersey.process.internal.RequestScope.runInScope(RequestScope.java:347)
at org.glassfish.jersey.server.ChunkedOutput.flushQueue(ChunkedOutput.java:190)
at org.glassfish.jersey.server.ChunkedOutput.write(ChunkedOutput.java:180)
at ch.company.app.controller.MyController$1.run(MyController.java:62)
at java.lang.Thread.run(Thread.java:745)
The weird thing is that sometimes, after a restart of Glassfish (4.1) and a new deployment, when calling the method I actually get the desired output from 1 to 90 times (without using the Thread.sleep() -> why it's in comments here) only to be followed again by the NullPointerException. And it only does this once as far as I can tell.
Output example before a NullPointerException:
: this is a test comment
event: message-to-client
id: c0
data: Hello world 0!
My web.xml regarding the jersey servlet 2.x container filter:
<filter>
<filter-name>jersey</filter-name>
<filter-class>org.glassfish.jersey.servlet.ServletContainer</filter-class>
<init-param>
<param-name>jersey.config.server.provider.packages</param-name>
<param-value>ch.company.app</param-value>
</init-param>
<init-param>
<param-name>jersey.config.servlet.filter.staticContentRegex</param-name>
<param-value>^.+?\.(?:bmp|gif|png|jpg|jpeg|ico|css|js|pdf|txt|svg|eot|otf|ttf|woff|map)$</param-value>
</init-param>
</filter>
<!--
<filter-mapping>
<filter-name>jersey</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
Since #ApplicationPath generates a Servlet 3.x container I decided to try Servlet 3.x with the following web.xml instead of the Servlet 2.x Filter but it also lead me to the same exception:
<servlet>
<servlet-name>javax.ws.rs.core.Application</servlet-name>
<init-param>
<param-name>jersey.config.server.provider.packages</param-name>
<param-value>ch.company.app</param-value>
</init-param>
<init-param>
<param-name>jersey.config.server.provider.classnames</param-name>
<param-value>org.glassfish.jersey.media.sse.SseFeature</param-value>
</init-param>
<init-param>
<param-name>jersey.config.disableMoxyJson</param-name>
<param-value>true</param-value>
</init-param>
<init-param>
<param-name>jersey.config.servlet.filter.staticContentRegex</param-name>
<param-value>^.+?\.(?:bmp|gif|png|jpg|jpeg|ico|css|js|pdf|txt|svg|eot|otf|ttf|woff|map)$</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>javax.ws.rs.core.Application</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping>
I even tried to add SseFeature manually (as suggested here: https://java.net/jira/browse/JERSEY-2150) which didn't help either and according to the SSE documentation it's only necessary till jersey version 2.8.
<init-param>
<param-name>jersey.config.server.provider.classnames</param-name>
<param-value>org.glassfish.jersey.media.sse.SseFeature</param-value>
</init-param>
So now I spent like two days to getting into this but I still can't figure it out.
Any ideas?
Update
I figured out that it only happens when Jersey is configured to run as a filter. I managed to make it work with Servlet 3.x and the web descriptor when omitting the init-params which are not applicable when Jersey is configured as a Servlet, as described here: https://jersey.java.net/apidocs/latest/jersey/org/glassfish/jersey/servlet/ServletProperties.html
<servlet>
<servlet-name>ch.company.app.ApplicationConfig</servlet-name>
<init-param>
<param-name>javax.ws.rs.Application</param-name>
<param-value>ch.company.app.ApplicationConfig</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>ch.company.app.ApplicationConfig</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping>
And the according class
public class ApplicationConfig extends Application {
#Override
public Set<Class<?>> getClasses() {
Set<Class<?>> resources = new java.util.HashSet<>();
addRestResourceClasses(resources);
return resources;
}
private void addRestResourceClasses(Set<Class<?>> resources) {
resources.add(ch.company.app.controller.AppController.class);
resources.add(ch.company.app.controller.IndexController.class);
}
}
Unfortunately I still can't figure out how to access my static ressources (css, js, images) with this approach as the FILTER_STATIC_CONTENT_REGEX is not available in Servlet configuration. (I will investigate this separately.)
So the question is: Why doesn't it work when Jersey is configured as a filter?
I'm trying to connect to a Jersey service using JQuery. But, it's not getting connected to the service, because I'm checking the logs whether it has hit the service or not. Is there anything missing?
$('#update').click(function() {
alert("updating the labelll");
$.ajax({
url:"/updatecontent",
type: 'POST',
dataType:"json",
data:$( "#labels option:selected" ).text(),
async:false,
success:function(contentdata) { // Success Call Back Function.
if(contentdata == "1") {
alert("successfully updated");
} else {
alert("sorry.. failed in updating");
}
},
error:function(){ // Error Call back function.
alert("sorry.. failed in updating in Error call back");
}
});
});
Service
---------
#Path("/updatecontent")
public class updatecontent {
private static final org.slf4j.Logger LOGGER=org.slf4j.LoggerFactory.getLogger(updatecontent.class);
#Context
HttpServletRequest request;
#Context
HttpServletResponse response;
#POST
#Consumes(MediaType.APPLICATION_JSON)
public String updateStatus(String packet) throws JSONException {
// Get the object from the UI.
LOGGER.info("In the API class of updating content for review.");
return "1";
}
}
Web.xml
---------
<servlet>
<servlet-name>jersey-serlvet</servlet-name>
<servlet-class>com.sun.jersey.spi.container.servlet.ServletContainer</servlet-class>
<init-param>
<param-name>com.sun.jersey.config.property.packages</param-name>
<param-value>net.my.services</param-value>
</init-param>
<init-param>
<param-name>com.sun.jersey.api.json.POJOMappingFeature</param-name>
<param-value>true</param-value>
</init-param>
<load-on-startup>6</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>jersey-serlvet</servlet-name>
<url-pattern>/rest/*</url-pattern>
</servlet-mapping>
Am I missing anything here? There should be a minor issue. Any ideas would be greatly appreciated.
Your web.xml has an url-pattern of
<url-pattern>/rest/*</url-pattern>
So jQuery must connect to
/rest/updatecontent
i'm new to JAX-RS. I'm trying to represent a List to a JSON array:
#GET
#Produces(MediaType.APPLICATION_JSON)
#Path("/getUsersResource/{userId}")
public List<AbstractResource> getUsersResources(#PathParam("userId") final String userId) {
if (userId == null) {
return null;
}
User user = null;
try {
user = userDao.getUserById(Integer.parseInt(userId));
} catch (NumberFormatException nfe) {
user = userDao.getUser(userId);
}
if (user == null) {
return null;
}
return abstractResourceDao.getUsersResources(null, user.userId);
}
When i execute this url i get:
{"exception": {"name": "WebApplicationException"}}
I annotated my AbstractResource class with the #XmlRootElement only and when i change the #Produces annotation parameter to
#Produces(MediaType.APPLICATION_XML)
I get the proper result. Here is my web.xml:
<servlet>
<servlet-name>REST Application</servlet-name>
<servlet-class>org.apache.wink.server.internal.servlet.RestServlet</servlet-class>
<init-param>
<param-name>javax.ws.rs.Application</param-name>
<param-value>com.balthaser.b3e.rest.RESTApplication</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet>
<servlet-name>REST Client</servlet-name>
<servlet-class>com.balthaser.b3e.rest.client.RESTClient</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>REST Client</servlet-name>
<url-pattern>/rest/index.html</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>REST Application</servlet-name>
<url-pattern>/rest/*</url-pattern>
</servlet-mapping>
Are there any additional requirements when producing JSON Arrays ?
Apache Wink is using json.org and jettison as a Json provider and they can't handle Java List properly.
So you need to configure Wink to use Jackson instead as a Json provider.
Here is the detail.
http://www.ibm.com/developerworks/java/library/wa-aj-jackson/index.html