I have an App Engine backend with Google Cloud Messaging setup in my local Android Studio.
It has the original endpoints as follows:
Messaging Endpoint
Registration Endpoint
I have created a new Java file and added a new class called UserRegistration as follows:
package com.xxxxx.gcmbackend;
import com.google.api.server.spi.config.Api;
import com.google.api.server.spi.config.ApiMethod;
import com.google.api.server.spi.config.ApiNamespace;
import com.google.api.server.spi.response.CollectionResponse;
import java.util.List;
import java.util.logging.Logger;
import javax.inject.Named;
import static com.xxxxxx.gcmbackend.OfyService.ofy;
#Api(
name = "register",
version = "v1",
namespace = #ApiNamespace(
ownerDomain = "gcmbackend.xxxxx.com",
ownerName = "gcmbackend.xxxxx.com",
packagePath=""
)
)
public class UserRegistrationEndpoint {
private static final Logger log = Logger.getLogger(RegistrationEndpoint.class.getName());
#ApiMethod(name = "register")
public void registerDevice(#Named("regId") String regId, #Named("username") String username, #Named("phone") String phone) {
if(findRecord(regId) != null) {
log.info("Device " + regId + " already registered, skipping register");
return;
}
RegistrationRecord record = new RegistrationRecord();
record.setRegId(regId);
record.setUsername(username);
record.setPhone(phone);
ofy().save().entity(record).now();
}
private RegistrationRecord findRecord(String regId) {
return ofy().load().type(RegistrationRecord.class).filter("regId", regId).first().now();
}
}
However, when deployed, I don't see this endpoint in the API explorer. How do I add a new working endpoint to an App Engine backend with Google Cloud Messaging?
Going through existing code structure, I found out that every new API must be added to the web.xml file. I added my new endpoint as:
<?xml version="1.0" encoding="utf-8"?>
<web-app xmlns="http://java.sun.com/xml/ns/javaee" version="2.5">
<filter>
<filter-name>ObjectifyFilter</filter-name>
<filter-class>com.googlecode.objectify.ObjectifyFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>ObjectifyFilter</filter-name>
<url-pattern></url-pattern>
</filter-mapping>
<servlet>
<servlet-name>SystemServiceServlet</servlet-name>
<servlet-class>com.google.api.server.spi.SystemServiceServlet</servlet-class>
<init-param>
<param-name>services</param-name>
<param-value>com.xxxxx.gcmbackend.RegistrationEndpoint, com.xxxxx.gcmbackend.MessagingEndpoint, com.xxxxx.gcmbackend.UserRegistrationEndpoint</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>SystemServiceServlet</servlet-name>
<url-pattern>/_ah/spi/*</url-pattern>
</servlet-mapping>
<welcome-file-list>
<welcome-file>index.html</welcome-file>
</welcome-file-list>
</web-app>
Related
This is my web.xml.
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" id="WebApp_ID" version="3.0">
<display-name>NewsPortal</display-name>
<welcome-file-list>
<welcome-file>index.html</welcome-file>
<welcome-file>index.htm</welcome-file>
<welcome-file>index.jsp</welcome-file>
<welcome-file>default.html</welcome-file>
<welcome-file>default.htm</welcome-file>
<welcome-file>default.jsp</welcome-file>
</welcome-file-list>
<servlet>
<servlet-name>javax.ws.rs.core.Application</servlet-name>
<init-param>
<param-name>com.sun.jersey.config.property.packages</param-name>
<param-value>com.newsportal</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>javax.ws.rs.core.Application</servlet-name>
<url-pattern>/rest/*</url-pattern>
</servlet-mapping>
</web-app>
There may be something wrong with web.xml but I am not sure.
Here is my web service .
package com.newsportal;
import javax.ws.rs.Consumes;
import javax.ws.rs.FormParam;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import com.newsportal.utility.ErrorReporting;
#Path("/Authentication")
public class AuthenticationResource {
#POST
#Consumes(MediaType.APPLICATION_FORM_URLENCODED)
#Produces(MediaType.APPLICATION_JSON)
#Path("/login")
public Response login(#FormParam("emailOrPhone") String emailOrPhone,#FormParam("password") String password){
String response ="";
try{
}catch(Exception ex){
ErrorReporting.webServiceError(ex);
}
return Response.ok(response)
.header("Access-Control-Allow-Origin", "*")
.build();
}
}
This is JAX-RS i think here most of the code looks fine .
Here is my jquery I am trying to invoke this login method
var Index = function() {
var handleIndexLoad = function() {
// no authentication at load
}
var handlelogin = function() {
var emailOrPhone='admin#nextolive.com';
var password ='12345';
$.ajax({
method : "POST",
url : "Authentication/login/",
data :'emailOrPhone='+ emailOrPhone +'&password='+password,
}).done(function(response) {
console.log(response);
});
}
return {
// main function to initiate the module
init : function() {
handleIndexLoad();
handlelogin();
}
};
}();
This is index.js file . I think here also things are fine .
To be honest I am new to Java so , i am not really sure if I am following
the right pattern .
Please tell me what i need to do fix it .
I need to enable the CORS headers on jersey server side because otherwise the Angualr frontend is getting:
XMLHttpRequest cannot load http://localhost:8080/api/products.
No 'Access-Control-Allow-Origin' header is present on the requested resource.
Origin 'http://localhost:9000' is therefore not allowed access.
As Jersey documentation explained I set up the filter and made it discoverable using web.xml:
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
<servlet>
<servlet-name>Jersey Web Application</servlet-name>
<servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class>
<init-param>
<param-name>javax.ws.rs.Application</param-name>
<param-value>ny.devtest.endtoend.config.ApplicationConfig</param-value>
<param-name>com.sun.jersey.spi.container.ContainerRequestFilters</param-name>
<param-name>ny.devtest.endtoend</param-name>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>Jersey Web Application</servlet-name>
<url-pattern>*</url-pattern>
</servlet-mapping>
</web-app>
The filter interceptior implementation:
package ny.devtest.endtoend;
import javax.ws.rs.container.ContainerRequestContext;
import javax.ws.rs.container.ContainerResponseContext;
import javax.ws.rs.container.ContainerResponseFilter;
import javax.ws.rs.ext.Provider;
import java.io.IOException;
#Provider
public class ResponseCorsFilter implements ContainerResponseFilter {
public ResponseCorsFilter() {
System.out.println("ServerResponseFilter initialization");
}
#Override
public void filter(ContainerRequestContext containerRequestContext, ContainerResponseContext containerResponseContext) throws IOException {
containerResponseContext.getHeaders().add("X-Powered-By", "Jersey :-)");
containerResponseContext.getHeaders().add("Access-Control-Allow-Origin", "*");
containerResponseContext.getHeaders().add("Access-Control-Allow-Methods", "GET, POST, OPTIONS");
}
}
It is not working.
UPDATE:
package ny.devtest.endtoend.config;
import ny.devtest.endtoend.api.OrderResource;
import org.eclipse.persistence.jaxb.BeanValidationMode;
import org.eclipse.persistence.jaxb.MarshallerProperties;
import org.glassfish.hk2.utilities.binding.AbstractBinder;
import org.glassfish.jersey.jackson.JacksonFeature;
import org.glassfish.jersey.moxy.json.MoxyJsonConfig;
import org.glassfish.jersey.moxy.json.MoxyJsonFeature;
import org.glassfish.jersey.server.ResourceConfig;
import org.glassfish.jersey.server.ServerProperties;
import org.glassfish.jersey.server.validation.ValidationConfig;
import org.glassfish.jersey.server.validation.internal.InjectingConstraintValidatorFactory;
import javax.validation.ParameterNameProvider;
import javax.validation.Validation;
import javax.ws.rs.container.ContainerRequestContext;
import javax.ws.rs.container.ContainerResponseContext;
import javax.ws.rs.container.ResourceContext;
import javax.ws.rs.core.Context;
import javax.ws.rs.ext.ContextResolver;
import java.io.IOException;
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.List;
public class ApplicationConfig extends ResourceConfig {
private void ApplicationInit(){
// Resources.
packages(OrderResource.class.getPackage().getName());
// Validation.
property(ServerProperties.BV_SEND_ERROR_IN_RESPONSE, true);
property(ServerProperties.BV_DISABLE_VALIDATE_ON_EXECUTABLE_OVERRIDE_CHECK, true);
// Providers - JSON.
register(JacksonFeature.class);
register(MoxyJsonFeature.class);
register(new MoxyJsonConfig().setFormattedOutput(true)
.property(MarshallerProperties.BEAN_VALIDATION_MODE, BeanValidationMode.NONE)
.resolver());
}
public ApplicationConfig() {
ApplicationInit();
// Bindings (#Inject)
register(new ApplicationBinder());
}
public ApplicationConfig(AbstractBinder customBinder) {
ApplicationInit();
register(customBinder);
}
#Override // << NOT WORKING
public void filter(ContainerRequestContext containerRequestContext, ContainerResponseContext containerResponseContext) throws IOException {
containerResponseContext.getHeaders().add("X-Powered-By", "Jersey :-)");
containerResponseContext.getHeaders().add("Access-Control-Allow-Origin", "*");
containerResponseContext.getHeaders().add("Access-Control-Allow-Methods", "GET, POST, OPTIONS");
}
}
Let's try it:
package ny.devtest.endtoend.config;
import org.glassfish.jersey.server.ResourceConfig;
import ...
public class ApplicationConfig extends ResourceConfig {
private void ApplicationInit(){
// Resources.
packages(OrderResource.class.getPackage().getName());
// Register CORS filter.
register(ny.devtest.endtoend.ResponseCorsFilter.class);
// Register the rest you need
...
}
public ApplicationConfig() {
ApplicationInit();
// Bindings (#Inject)
register(new ApplicationBinder());
}
...
}
And configure in web.xml like that
<servlet>
<servlet-name>Jersey Web Application</servlet-name>
<servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class>
<init-param>
<param-name>javax.ws.rs.Application</param-name>
<param-value>ny.devtest.endtoend.config.ApplicationConfig</param-value>
</init-param>
<!-- Add parameter for CORS filter -->
<init-param>
<param-name>jersey.config.server.provider.packages</param-name>
<param-value>
ny.devtest.endtoend
</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>Jersey Web Application</servlet-name>
<url-pattern>*</url-pattern>
</servlet-mapping>
There are a few options to configure this
The way you are trying to do (in the web.xml). With this, you are 1) specifying the wrong init-param name. It should be jersey.config.server.provider.classnames and 2) You need to specify the (fully qualified) name of the filter class as the init-param value, not the package.
You have a java configuration class (ApplicationConfig), so you can just register the filter there
If you are using package (or classpath) scanning it should automatically pick up the filter and register it, because of the #Provider annotation.
For help with 2 or 3, please show your ApplicationConfig class. I'm not sure if you are directly subclassing Application or ResourceConfig. They are different in how they are configured.
I've just started my first simple spring program. I'm trying to make a Rest API using Jersey framework with spring. Its a very basic simple program to fetch list of countries. But, however it throws the error. I've gone through other solutions, none of them worked.
Web.xml
<web-app id="WebApp_ID" version="2.4"
xmlns="http://java.sun.com/xml/ns/j2ee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee
http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
<display-name>Spring MVC Application</display-name>
<servlet>
<servlet-name>HelloWeb</servlet-name>
<servlet-class>
org.springframework.web.servlet.DispatcherServlet
</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>HelloWeb</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
<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.api.json.POJOMappingFeature</param-name>
<param-value>true</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>jersey-serlvet</servlet-name>
<url-pattern>/rest/*</url-pattern>
</servlet-mapping>
</web-app>
Error which I get is
SEVERE: StandardWrapper.Throwable
com.sun.jersey.api.container.ContainerException: The ResourceConfig instance does not contain any root resource classes.
at com.sun.jersey.server.impl.application.RootResourceUriRules.<init>(RootResourceUriRules.java:99)
at com.sun.jersey.server.impl.application.WebApplicationImpl._initiate(WebApplicationImpl.java:1359)
at com.sun.jersey.server.impl.application.WebApplicationImpl.access$700(WebApplicationImpl.java:180)
at com.sun.jersey.server.impl.application.WebApplicationImpl$13.f(WebApplicationImpl.java:799)
at com.sun.jersey.server.impl.application.WebApplicationImpl$13.f(WebApplicationImpl.java:795)
at com.sun.jersey.spi.inject.Errors.processWithErrors(Errors.java:193)
My program
package org.arpit.java2blog.jaxrs;
import java.util.ArrayList;
import java.util.List;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import org.arpit.java2blog.bean.Country;
#Path("/countries")
public class CountryRestService {
#GET
#Produces(MediaType.APPLICATION_JSON)
public List<Country> getCountries() {
System.out.println("Getting countries");
List<Country> listOfCountries = new ArrayList<Country>();
listOfCountries = createCountryList();
return listOfCountries;
}
#GET
#Path("{id: \\d+}")
#Produces(MediaType.APPLICATION_JSON)
public Country getCountryById(#PathParam("id") int id) {
List<Country> listOfCountries = new ArrayList<Country>();
listOfCountries = createCountryList();
for (Country country : listOfCountries) {
if (country.getId() == id)
return country;
}
return null;
}
// Utiliy method to create country list.
public List<Country> createCountryList() {
Country indiaCountry = new Country(1, "India");
Country chinaCountry = new Country(4, "China");
Country nepalCountry = new Country(3, "Nepal");
Country bhutanCountry = new Country(2, "Bhutan");
List<Country> listOfCountries = new ArrayList<Country>();
listOfCountries.add(indiaCountry);
listOfCountries.add(chinaCountry);
listOfCountries.add(nepalCountry);
listOfCountries.add(bhutanCountry);
return listOfCountries;
}
}
URL
http://localhost:8080/HelloWeb/rest/countries
What is missing in this one?
You don't have your Jersey servlet (ServletContainer) configured in your web.xml to pick up any resource classes. So Jersey starts up with no resources registered.
With web.xml generally the way to go, is to set an init-param to tell Jersey to scan a certain package for classes annotated with #Path and #Provider. To do that, just add the following
<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>the.package.you.want.to.scan</param-value>
</init-param>
...
</servlet>
I am new to developing REST API with Java. I made a very simple one using the mkyong tutorials, where it only says "hello". I am using Apache Tomcat.
Now I am trying to develop a one where it will return the JSON objects. I am attempting the example here - http://www.mkyong.com/webservices/jax-rs/json-example-with-jersey-jackson/. Some of the code are changed (ex: package name).Below is my code.
Track.java
package com.tutorialspoint;
/**
*
* #author Yohan
*/
public class Track {
String title;
String singer;
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getSinger() {
return singer;
}
public void setSinger(String singer) {
this.singer = singer;
}
#Override
public String toString() {
return "Track [title=" + title + ", singer=" + singer + "]";
}
}
JsonService.java
package com.tutorialspoint;
import javax.ws.rs.Consumes;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
/**
*
* #author Yohan
*/
#Path("/json/metallica")
public class JsonService {
#GET
#Path("/get")
#Produces(MediaType.APPLICATION_JSON)
public Track getTrackInJSON() {
Track track = new Track();
track.setTitle("Enter Sandman");
track.setSinger("Metallica");
return track;
}
#POST
#Path("/post")
#Consumes(MediaType.APPLICATION_JSON)
public Response createTrackInJSON(Track track) {
String result = "Track saved : " + track;
return Response.status(201).entity(result).build();
}
}
Web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="3.0" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd">
<display-name>Restful Web Application</display-name>
<servlet>
<servlet-name>NewServlet</servlet-name>
<servlet-class>NewServlet</servlet-class>
</servlet>
<servlet>
<servlet-name>Jersey RESTful Application</servlet-name>
<servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class>
<init-param>
<param-name>jersey.config.server.provider.packages</param-name>
<param-value>com.tutorialspoint</param-value>
</init-param>
<init-param>
<param-name>com.sun.jersey.api.json.POJOMappingFeature</param-name>
<param-value>true</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>NewServlet</servlet-name>
<url-pattern>/NewServlet</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>Jersey RESTful Application</servlet-name>
<url-pattern>/rest/*</url-pattern>
</servlet-mapping>
<session-config>
<session-timeout>
30
</session-timeout>
</session-config>
</web-app>
My application is not a marven project. So the added libraries are below.
I tested the application with the below URL.
http://localhost:8080/RESTFUL_API_SAMPLE/rest/json/metallica/get
All I got is the below page
Any idea about why I am not getting the expected result?
Currently you don't have any JSON/POJO support. The jersey-json jar and the POJOMappingFeature configuration in your web.xml is for Jersey 1.x, which won't work for Jersey 2.x. For all the jars you need for Jersey 2.x support, see this answer.
I have created a simple webservice but I am unable to call it. I get 404 Not found error.
package com.fms.mdw.rest;
#Path("/Search")
public class SearchWebService {
#POST
#Path("/searchData")
#Consumes(MediaType.APPLICATION_JSON)
#Produces("application/json")
public FMSResponseInfo getSearchData(SearchDTO searchDTO) {
System.out.println("Entered the getSearchData()");
FMSResponseInfo fmsResponseInfo = new FMSResponseInfo();
List<SearchDetailsDTO> searchDetailsDtoList = new ArrayList<>();
for (int i = 0; i < 5; i++) {
SearchDetailsDTO searchDetailsDto = new SearchDetailsDTO();
searchDetailsDto.setBarcode("barcode" + i);
searchDetailsDto.setDocNo("docNo" + i);
searchDetailsDto.setDocType("docType" + i);
searchDetailsDtoList.add(searchDetailsDto);
}
fmsResponseInfo.setStatus("200");
fmsResponseInfo.setMessage("Success");
fmsResponseInfo.setData(searchDetailsDtoList);
System.out.println("Leaving the getSearchData()");
return fmsResponseInfo;
}
}
SearchDTO has two fields searchType, searchText both of type string.So the json payload will be {"searchType":"", "searchText":""}
I have registered the webservice in the following manner in web.xml :
<?xml version="1.0" encoding="UTF-8"?>
<web-app id="WebApp_ID" version="3.0"
xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd">
<display-name>LatestFMS</display-name>
<welcome-file-list>
<welcome-file>index.html</welcome-file>
</welcome-file-list>
<servlet>
<servlet-name>LatestFMS Web Application</servlet-name>
<servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class>
<init-param>
<param-name>jersey.config.server.provider.packages</param-name>
<param-value>com.fms.mdw.rest</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>LatestFMS Web Application</servlet-name>
<url-pattern>/rest/*</url-pattern>
</servlet-mapping>
</web-app>
I am able to access the webpages, but I am unable to call the webservice. I am using RESTClient to send post request. The web server is apache tomcat 7 and jersey 2.16 .
The url I am hitting is http://localhost:8082/LatestFMS/rest/Search/searchData.
I am unable to resolve the issue, please help ! ! !