I have a Java Application in Eclipse. Using Jersey, it successfully creates a webpage locally (localhost).
The problem is I have a javascript on another server trying to access that webpage and it throws a CORS error.
Is there any built-in CORS support for Jersey/WADL applications?
I've tried creating a Jersey filter that supports CORS - following these instructions. No luck. :( I'm looking into this, but am unsure if it is the right choice for what I want to do.
Essentially, my header is currently this:
But I want it to look something like this:
Thanks all!
EDIT:
As per jgm's suggestion, I have created a filter (called CORSFilter) and added the requesite dependencies. Am I registering the filter correctly in the web.xml file?
<?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" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" version="3.0">
<display-name>createJPA</display-name>
<servlet>
<servlet-name>Jersey Root REST Service</servlet-name>
<servlet-class>com.sun.jersey.spi.container.servlet.ServletContainer</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>Jersey Root REST Service</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping>
<filter>
<filter-name>CORSFilter</filter-name>
<filter-class>model.producer.CORSFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>CORSFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
</web-app>
Here is a simple CORS filter for jersey, adapted from the Weald Technology utilities:
import com.google.inject.Inject;
import com.sun.jersey.spi.container.ContainerRequest;
import com.sun.jersey.spi.container.ContainerResponse;
import com.sun.jersey.spi.container.ContainerResponseFilter;
import com.wealdtech.jersey.CORSConfiguration;
/**
* Filter to handle cross-origin resource sharing.
*/
public class CORSFilter implements ContainerResponseFilter
{
private static final String ACAOHEADER = "Access-Control-Allow-Origin";
private static final String ACRHHEADER = "Access-Control-Request-Headers";
private static final String ACAHHEADER = "Access-Control-Allow-Headers";
private static final String ACAMHEADER = "Access-Control-Allow-Methods";
private static final String ACACHEADER = "Access-Control-Allow-Credentials";
private final transient CORSConfiguration configuration;
#Inject
public CORSFilter(final CORSConfiguration configuration)
{
this.configuration = configuration;
}
#Override
public ContainerResponse filter(final ContainerRequest request, final ContainerResponse response)
{
response.getHttpHeaders().add(ACAOHEADER, this.configuration.getOrigin());
final String requestHeaders = request.getHeaderValue(ACRHHEADER);
response.getHttpHeaders().add(ACAHHEADER, requestHeaders);
response.getHttpHeaders().add(ACAMHEADER, this.configuration.getAllowedMethods());
response.getHttpHeaders().add(ACACHEADER, this.configuration.allowCredentials());
return response;
}
}
For the configuration you can either use the existing configuration setup or incorporate it in to your own system. Note that this uses Google Guice to inject the configuration, if you aren't using Guice you'll need to do this manually.
Related
I have an existing code like below one that uploads a single image.
public class ImageRoute extends RouteBuilder {
#Override
public void configure() throws Exception {
getContext().setTracing(true);
getContext().setStreamCaching(true);
from("servlet:///PushImage?servletName=CamelServlet")
.to("direct:doImageUploadJob")
.marshal().json(JsonLibrary.Jackson);
from("direct:doImageUploadJob")
.process(new Processor() {
#Override
public void process(Exchange exchange) throws Exception {
Message in = exchange.getIn();
Set<String> names = in.getAttachmentNames();
Object[] arrayNames = names.toArray();
System.out.println("image array size::"+ arrayNames.length);
Map<String, DataHandler> attchmentMaps = in.getAttachments();
System.out.println("image map size::"+ attchmentMaps.size());
}
});
}
}
and in web.xml following configuration is there.
<!-- Camel servlet -->
<servlet>
<servlet-name>CamelServlet</servlet-name>
<servlet-class>org.apache.camel.component.servlet.CamelHttpTransportServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<!-- Camel servlet mapping -->
<servlet-mapping>
<servlet-name>CamelServlet</servlet-name>
<url-pattern>/exmpattrn/*</url-pattern>
</servlet-mapping>
<filter>
<filter-name>MultipartFilter</filter-name>
<filter-class>org.eclipse.jetty.servlets.MultiPartFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>MultipartFilter</filter-name>
<servlet-name>CamelServlet</servlet-name>
</filter-mapping>
But if I try to upload more than one image by calling this API through Postman, it is uploading only the last image selected.
I tried to print the attachment size, but it is always printing as 1.
I don't know why.
Can anybody help me?
I am using Spring 4.1.1 with Java 7.
I am using camel Apache Camel 2.14.0 restlet to form APIs.
I have created a Wicket application that has recently been upgraded with the wicket REST functionality. When developing it and running through Jetty, I am able to post messages to the REST service correctly. However when it is deployed to tomcat, going to the REST URL gives a 404 error and a 'requested resource is not available' response.
Pom entries:
wicketstuff-annotation, wicketstuff-restannotations, wicketstuff-restannotations-json (all jar/compile, version identical to wicket version 6.24.0)
Code in the rest class
public class Webhook extends AbstractRestResource<JsonWebSerialDeserial> {
#MethodMapping(value="/notification", httpMethod=HttpMethod.POST, consumes= RestMimeTypes.APPLICATION_JSON, produces = RestMimeTypes.TEXT_PLAIN)
public String notification( #RequestBody Notification data ) {
// do some things
return "received successfully";
}
#Override
public String getMountPath() {
return "/emailcampaign/webhook";
}
}
The REST class is initialized in WicketApplication:
public void init() {
final Webhook hook = new Webhook();
mountResource( hook.getMountPath(), new ResourceReference( hook.getClass().getSimpleName() ) {
private static final long serialVersionUID = 1L;
public IResource getResource() {
return hook;
}
});
}
The tomcat localhost_access_logs have this:
`XX.XX.XX.XX - - [01/Feb/2018:06:46:10 +0000] "POST /emailcampaign/webhook/notification HTTP/1.1" 404 1041
The system starts up correctly, so I don't appear to be missing any jar files on deployment, so I'm at a loss. Can anyone help please?
Tomcat 7.0.67, Jetty 7.6.3, Wicket 6.24, Spring 4.1.4
Edit: This is the content of the web.xml:
<?xml version="1.0" encoding="ISO-8859-1"?>
<web-app 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"
version="2.5">
<display-name>system-ui</display-name>
<context-param>
<param-name>configuration</param-name>
<param-value>deployment</param-value>
</context-param>
<filter>
<filter-name>wicket.system-ui</filter-name>
<filter-class>org.apache.wicket.protocol.http.WicketFilter</filter-class>
<init-param>
<param-name>applicationClassName</param-name>
<param-value>com.sw.system.ui.WicketApplication</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>wicket.system-ui</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
</web-app>
....aaand this was down to a rookie oversight.
On my development machine, the path to the application on jetty was http://localhost:8080. On the deployment machine, it's http://[server_name]/theapp. So I set the Client REST URL to point to http://[server_name]/theapp/emailcampaign/webhook/notification (ie add the theapp subpath) and it worked!
Doh but hopefully it helps someone else out.
i have a problem with writing a REST API. I wrote a little client to test the service, but i keep getting exceptions and errors.
Here's some of my code:
The deployment descriptor:
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee
http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd" id="WebApp_ID" version="3.1">
<display-name>com.boss.rest.example</display-name>
<welcome-file-list>
<welcome-file>index.jsp</welcome-file>
</welcome-file-list>
<servlet>
<servlet-name>ConfigServlet</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>rest</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>ConfigServlet</servlet-name>
<url-pattern>/api/*</url-pattern>
</servlet-mapping>
</web-app>
The client code:
public static void main(String[] args)
try {
String url_str = "http://localhost:8080/com.boss.rest.example/api/getRandomRamp";
URL url = new URL(url_str);
HttpURLConnection c = (HttpURLConnection) url.openConnection();
c.setRequestMethod("GET");
c.setRequestProperty("Accept", "application/json");
System.out.println("Response code: " + c.getResponseCode());
System.out.println(c.getInputStream().toString());
} catch (IOException ioe) {
ioe.printStackTrace();
}
}
And the servlet code:
#Path("/api")
public class ConfigServlet {
#Context
UriInfo uriInfo;
#GET
#Path("/getRandomRamp")
#Produces(MediaType.APPLICATION_JSON)
public Response getRandomRamp() {
String s = ">> This is just a random string, no real interaction with the backend available yet! <<";
System.out.println("Service SysOut: " + s);
return Response.status(200).entity(s).build();
}
}
With this code i get a FileNotFoundException for the given URL. Can anyone help? Thanks a lot!
You seem to have an issue with your api path. You have defined root path("/api/") at 2 places. Once in your deployment descriptor and the other in your Servlet. Change one of them to ("/")
I believe its the url which is causing the issue. seems like the context you are using contains the periods which is not a valid context name. trying changing the url to the application name(context) and it should work.
so
replace
"http://localhost:8080/com.boss.rest.example/api/getRandomRamp"
with
"http://localhost:8080/contextname/api/getRandomRamp"
How you deploy your application? Usually you have to do it to some server like Tomcat - and this server deploys it by certain name.
Also, display-name is Display Name, nothing else. Especially not deployment location.
I am pretty new to this whole servlet thing, so please correct me if I mix or use incorrect/confusing terms for things. I am however writing a blog ping server in Java using JAX-RS (Jersey), and I'm facing a problem where I have one servlet class that accepts REST input, and another servlet class that lists the same content.
Right now they are sharing their objects through a class that looks like this:
public class BlogPingUtils {
private static final String LIST_OF_CHANGES = "listOfChanges";
public static List<PingInfo> getListOfChanges(ServletContext context) {
List<PingInfo> listOfChanges = (List<PingInfo>)context.getAttribute(LIST_OF_CHANGES);
if(listOfChanges == null) listOfChanges = new ArrayList<PingInfo>();
return listOfChanges;
}
public static void setListOfChanges(ServletContext context, List<PingInfo> listOfChanges) {
context.setAttribute(LIST_OF_CHANGES, listOfChanges);
}
}
This works in a small-scale development environment, but it feels dirty and probably wouldn't work in a heavy-duty production environment because of concurrency issues and such. Also it's not very flexible. What I would like to do is have an interface that would have methods for reading and writing data. Then I would inject an object of a class that implements this interface into these two servlets, so that they are actually using the same object for interacting with the data. This would then be backed by a synchronized list or database transactions or something.
What would be the preferred way to do this? Is it possible? My web.xml is very simple right now and looks like this:
<?xml version="1.0" encoding="UTF-8"?>
<web-app 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" version="2.4">
<display-name>Blog Ping</display-name>
<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.packages</param-name>
<param-value>com.vrutberg.blogping</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>
</web-app>
Rather than a static class, I would design an Interface with your getters and setters, than create an implementation class.
I would then register the singleton (or pool depending on your needs) implementation class with a thread-safe central repository visible by both servlets, such as JNDI.
The servlets query the central repository and 'cast' to the interface.
I create guice servlet like this:
public class GuiceApplicationServlet extends AbstractApplicationServlet {
protected Provider<Application> applicationProvider;
public GuiceApplicationServlet() {
System.out.println("TTest");
}
#Inject
public GuiceApplicationServlet(Provider<Application> applicationProvider) {
super();
this.applicationProvider = applicationProvider;
System.out.println("Test");
}
#Override
protected Class<? extends Application> getApplicationClass()
throws ClassNotFoundException {
return Application.class;
}
#Override
protected Application getNewApplication(HttpServletRequest request)
throws ServletException {
return applicationProvider.get();
}
}
web.xml:
<filter>
<filter-name>guiceFilter</filter-name>
<filter-class>com.google.inject.servlet.GuiceFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>guiceFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<listener>
<listener-class>pl.koziolekweb.vaadin.guice.servlet.VaadinGuiceConfiguration</listener-class>
</listener>
<servlet>
<servlet-name>Vaadin Application Servlet</servlet-name>
<servlet-class>pl.koziolekweb.vaadin.guice.servlet.GuiceApplicationServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>Vaadin Application Servlet</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping>
The problem is that when I run jetty then Guice create instance of servlet (print "Test" in console) but when I try to run application in browser i get NPE and in console "TTest" appear.
So jetty create another instance of servlet that is not managed by guice.
Question is how to configure jetty to use only guice?
You have to create a guice servlet module which extends com.google.inject.servlet.ServletModule (let's call it FooModule). You define there your bindings and paths to servlets by overriding configureServlets() method.
Then you must create context listener by extending com.google.inject.servlet.GuiceServletContextListener (let's call it BarContextListener). There you must implement getInjector() method, with something like that:
protected Injector getInjector() {
Injector injector = Guice.createInjector(new FooModule());
return injector;
}
Then you remove all servlet mappings from your web.xml, and then put filter:
<filter>
<filter-name>guiceFilter</filter-name>
<filter-class>com.google.inject.servlet.GuiceFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>guiceFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
and context listener You created:
<listener>
<listener-class>path.to.package.of.context.listener.BarContextListener</listener-class>
</listener>
By this all Your servlets are managed by Guice and enable dependency injection in server side of Your application. It works for me in Tomcat so it should also work on Jetty. Don't forget to include guice-servlet-<version>.jar into your classpath. I didn't use it with Vaadin, but I guess my answer helped You little bit.
Because Guice should create all your Servlet instances, you have to remove the servlet and servlet-mapping entries from your web.xml file.
I have written a blog post on the subject, I'm sure it would be most helpful :
Vaadin + GAE + Guice-Servlet - TUTORIAL