I'm using SpringMVC.I want to call an XML file with web service in order to parse it later.The problem is that I can't access the XML file, I have got this error:No 'Access-Control-Allow-Origin' header is present on the requested resource.I have tried the solution below:
I created a new class which purpose is to add Access-Control-Allow-Origin' header on the requested ressource.This is the class
package com.mycompany.myapp;
import java.io.IOException;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class JsonpFilter implements Filter {
private String functionName;
#Override
public void destroy() {
}
#Override
public void doFilter(ServletRequest request, ServletResponse servletResponse,
FilterChain chain) throws IOException, ServletException {
if (!(request instanceof HttpServletRequest)) {
throw new ServletException("This filter can "
+ " only process HttpServletRequest requests");
}
HttpServletRequest httpRequest = (HttpServletRequest) request;
HttpServletResponse response = (HttpServletResponse) servletResponse;
if (isJSONPRequest(httpRequest)) {
ServletOutputStream out = response.getOutputStream();
out.println(getCallbackMethod(httpRequest) + "(");
chain.doFilter(request, response);
out.println(");");
response.setContentType("text/javascript");
} else {
response.addHeader("Access-Control-Allow-Origin", "*");
chain.doFilter(request, response);
}
}
#Override
public void init(FilterConfig filterConfig) throws ServletException {
this.functionName = filterConfig.getInitParameter("encoding");
if(this.functionName == null || this.functionName.length() <= 0) {
this.functionName = "callback";
}
}
private String getCallbackMethod(HttpServletRequest httpRequest) {
return httpRequest.getParameter(this.functionName);
}
private boolean isJSONPRequest(HttpServletRequest httpRequest) {
String callbackMethod = getCallbackMethod(httpRequest);
return (callbackMethod != null && callbackMethod.length() > 0);
}
}
then I add the these two lines in my web.xml file:
<display-name>DataServices</display-name>
<filter>
<filter-name>JSONPRequestFilter</filter-name>
<filter-class> com.mycompany.myapp.JsonpFilter</filter-class>
<init-param>
<param-name>functionName</param-name>
<param-value>callback</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>JSONPRequestFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
I don't have any complilation problem, but I still have the same error in the console at the execution time.So, the 'Access-Control-Allow-Origin' header isn't taken into account.
Please,If you can find out what is wrong with my program, or suggest me another solution, I will be thankful
To do this implement this interface
org.springframework.web.servlet.HandlerInterceptor
here is an example
#Component
public class CORSInterceptor implements HandlerInterceptor{
private static final Log LOG = LogFactory.getLog(CORSInterceptor.class);
#Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
LOG.trace("sending headers");
response.setHeader("Access-Control-Allow-Origin", "*");
response.setHeader("Access-Control-Allow-Methods", "POST, GET, PUT, DELETE");
response.setHeader("Access-Control-Max-Age", "3600");
response.setHeader("Access-Control-Allow-Headers", "x-requested-with");
return true;
}
#Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView)
throws Exception {
}
#Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
throws Exception {
LOG.trace("afterCompletion is called");
}
}
Then add this line to your application context
<mvc:interceptors>
<bean class="com.elm.mb.rest.interceptors.CORSInterceptor" />
</mvc:interceptors>
Related
I want to read request header from SOAP incoming request in my Java code for some authorization purpose. I found few work-arounds like using SOAPHandlers and . Code as below :
`package com.cerillion.ccs.framework;
import java.util.HashSet;
import java.util.Set;
import javax.xml.namespace.QName;
import javax.xml.soap.SOAPException;
import javax.xml.soap.SOAPHeader;
import javax.xml.soap.SOAPMessage;
import javax.xml.ws.handler.MessageContext;
import javax.xml.ws.handler.soap.SOAPHandler;
import javax.xml.ws.handler.soap.SOAPMessageContext;
import org.apache.log4j.Logger;
public class ApiSoapHandler implements SOAPHandler<SOAPMessageContext> {
private static final Logger logger = Logger.getLogger(ApiSoapHandler.class.getName());
#Override
public void close(MessageContext arg0) {
// TODO Auto-generated method stub
}
#Override
public boolean handleFault(SOAPMessageContext context) {
// TODO Auto-generated method stub
return false;
}
#Override
public boolean handleMessage(SOAPMessageContext context) {
logger.debug("Inside ApiSoapHandler");
try {
SOAPMessage message = context.getMessage();
SOAPHeader header = message.getSOAPHeader();
message.saveChanges();
} catch (SOAPException e) {
logger.error("Error occurred while adding credentials to SOAP header.",
e);
}
return true;
}
#Override
public Set<QName> getHeaders() {
/* QName securityTokenHeader = new QName("urn:com.intertech.secty", "token");
//new QName(“urn:com.intertech.secty”,“username”);
HashSet<QName> headers = new HashSet<QName>();
headers.add(securityTokenHeader);
return headers;*/
return null;
} }`
I ma really curious about to have some other simple alternative rather than writing entire handler just for fetching custom header tag. Is this the only way to read SOAP request header ? Any leads are really appreciated
My Jetty is servicing requests on /myservice/*
My problem is that when the server's queue gets full, the health check requests on /healthcheck start failing.
Is it possible to have a separate queue for my health checks, or is there another way to do this?import java.io.IOException;
Here is an example server:
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.servlet.ServletHandler;
import org.eclipse.jetty.util.thread.QueuedThreadPool;
/**
* Based on:
* https://www.eclipse.org/jetty/documentation/9.4.x/embedded-examples.html
*/
public class HealthCheckServer
{
public static void main( String[] args ) throws Exception
{
Server server = new Server(8086);
QueuedThreadPool qtp = (QueuedThreadPool) server.getThreadPool();
qtp.setMaxThreads(6);
ServletHandler handler = new ServletHandler();
server.setHandler(handler);
handler.addServletWithMapping(HelloServlet.class, "/hello");
handler.addServletWithMapping(HealthServlet.class, "/health");
server.start();
server.join();
}
#SuppressWarnings("serial")
public static class HelloServlet extends HttpServlet
{
#Override
protected void doGet( HttpServletRequest request,
HttpServletResponse response ) throws ServletException,
IOException
{
try {
Thread.sleep(10*1000); // 10 sec
} catch (InterruptedException e) {
e.printStackTrace();
}
response.setContentType("text/html");
response.setStatus(HttpServletResponse.SC_OK);
response.getWriter().println("<h1>Hello from HelloServlet</h1>");
}
}
#SuppressWarnings("serial")
public static class HealthServlet extends HttpServlet
{
#Override
protected void doGet( HttpServletRequest request,
HttpServletResponse response ) throws ServletException,
IOException
{
response.setContentType("text/html");
response.setStatus(HttpServletResponse.SC_OK);
response.getWriter().println("all good captain");
}
}
}
If you hit http://localhost:8086/hello 4 times, then http://localhost:8086/health won't be responsive.
My clients wanted to access wsdl using ?wsdl notation, but the springboot service i have created is working with only '.wsdl' format. I need a working example/sample how to configure Tuckey urlrewrite in the springboot application.
I have tried using below code, but the application complaints as it cant find urlrewrite.xml (which i have placed in src/main/resources folder.
Q1: How can i make my service to be accessible using url below
http://localhost:8080/ws/organisation?wsdl
I have tried using below code, but tuckey cannot find the urlrewrite.xml which is under src/java/resources.
#Bean
public FilterRegistrationBean tuckeyRegistrationBean() {
final FilterRegistrationBean registrationBean = new ilterRegistrationBean();
registrationBean.setFilter(new UrlRewriteFilter());
registrationBean.addInitParameter("confPath", "urlrewrite.xml");
return registrationBean;
}
Finally I could figure out a solution. This is now reading urlrewrite.xml from the src/main/resources folder.
No need to declare above mentioned bean definition in the question post (public FilterRegistrationBean tuckeyRegistrationBean()), as the below code declared as #Component will automatically register with context and url-rewriting is performed.
#Component
public class WsdlUrlRewriteFilter extends UrlRewriteFilter {
private static final String CONFIG_LOCATION = "classpath:/urlrewrite.xml";
#Value(CONFIG_LOCATION)
private Resource resource;
#Override
protected void loadUrlRewriter(FilterConfig filterConfig) throws ServletException {
try {
Conf conf = new Conf(filterConfig.getServletContext(), resource.getInputStream(), resource.getFilename(), "");
checkConf(conf);
} catch (IOException ex) {
throw new ServletException("Unable to load URL-rewrite configuration file from " + CONFIG_LOCATION, ex);
}
}
}
Best option is to write your own filter as follows.You can make use of HttpServletRequestWrapper to handle the ?wsdl extension and let the server handle the request.
import org.springframework.stereotype.Component;
import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
import java.io.IOException;
#Component
public class WSDLQuestionMarkReplaceFilter implements Filter {
#Override
public void init(FilterConfig filterConfig) throws ServletException {
//put init logs
}
#Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
HttpServletRequest httpRequest = (HttpServletRequest) request;
if ("wsdl".equalsIgnoreCase(httpRequest.getQueryString())) {
HttpServletRequestWrapper requestWrapper = new HttpServletRequestWrapper(httpRequest) {
#Override
public String getQueryString() {
return null;
}
#Override
public String getRequestURI() {
return super.getRequestURI() + ".wsdl";
}
};
chain.doFilter(requestWrapper, response);
} else {
chain.doFilter(request, response);
}
}
#Override
public void destroy() {
//put destroy logs
}
}
It worked for me. Hope it works for others too. SpringBoot+JAR
Please use the following dependency
<dependency>
<groupId>org.tuckey</groupId>
<artifactId>urlrewritefilter</artifactId>
<version>4.0.4</version>
</dependency>
Created urlrewrite.xml in resource folder
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE urlrewrite
PUBLIC "-//tuckey.org//DTD UrlRewrite 3.0//EN"
"http://www.tuckey.org/res/dtds/urlrewrite3.0.dtd">
<urlrewrite>
<rule>
<name>Domain Name Check</name>
<condition name="host" operator="notequal">www.userdomain.com</condition>
<from>^(.*)$</from>
<to type="redirect">http://www.userdomain.com$1</to>
</rule>
Added in main ApplicationRunner.java
#Bean
public FilterRegistrationBean tuckeyRegistrationBean() {
final FilterRegistrationBean registrationBean = new FilterRegistrationBean();
registrationBean.setFilter(new CustomURLRewriter());
return registrationBean;
}
And created a CustomURLRewriter
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.env.Environment;
import org.springframework.core.io.ClassPathResource;
import org.tuckey.web.filters.urlrewrite.Conf;
import org.tuckey.web.filters.urlrewrite.UrlRewriteFilter;
import org.tuckey.web.filters.urlrewrite.UrlRewriter;
import javax.servlet.*;
import java.io.InputStream;
public class CustomURLRewriter extends UrlRewriteFilter {
private UrlRewriter urlRewriter;
#Autowired
Environment env;
#Override
public void loadUrlRewriter(FilterConfig filterConfig) throws ServletException {
try {
ClassPathResource classPathResource = new ClassPathResource("urlrewrite.xml");
InputStream inputStream = classPathResource.getInputStream();
Conf conf1 = new Conf(filterConfig.getServletContext(), inputStream, "urlrewrite.xml", "");
urlRewriter = new UrlRewriter(conf1);
} catch (Exception e) {
throw new ServletException(e);
}
}
#Override
public UrlRewriter getUrlRewriter(ServletRequest request, ServletResponse response, FilterChain chain) {
return urlRewriter;
}
#Override
public void destroyUrlRewriter() {
if(urlRewriter != null)
urlRewriter.destroy();
}
}
I've set up a SOAP WebServiceProvider in JAX-WS, but I'm having trouble figuring out how to get request and response in XML format from a SOAP request and response. Here's a sample of the code I've got right now, and where I'm trying to grab the XML:
package com.ewb.socialbanking.creditcardMain;
import org.springframework.ws.client.core.support.WebServiceGatewaySupport;
import org.springframework.ws.soap.client.core.SoapActionCallback;
import com.ewb.socialbanking.creditcardws.GetCcNumber;
import com.ewb.socialbanking.creditcardws.GetCcNumberResponse;
import com.safenet.wsdl.LoginUser;
/*THIS IS HOW I AM GIVING THE REQUEST :
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();
ctx.register(CreditCardConfig.class);
ctx.refresh();
CreditCardClient cCClient = ctx.getBean(CreditCardClient.class);
GetCcNumber cCNumber = new GetCcNumber();
ObjectFactory enrollObjFactory = new ObjectFactory();
cCNumber.setT24Cif(enrollObjFactory.createString("abc"));
cCNumber.setLinkId(enrollObjFactory.createString("def"));
cCNumber.setCcCif(enrollObjFactory.createString("ghi"));
cCNumber.setMsgRefNo(enrollObjFactory.createString("jkl"));
GetCcNumberResponse valueForRes = cCClient.getCreditCardDetails(cCNumber);*/
public class CreditCardClient extends WebServiceGatewaySupport {
public GetCcNumberResponse getCreditCardDetails(GetCcNumber request) {
//I want here request in xml format??
System.out.println("req : "+request);
//Right now it is coming as :
//req : com.ewb.socialbanking.creditcardws.GetCcNumber#5d534f5d
GetCcNumberResponse response = null;
try {
response = (GetCcNumberResponse) getWebServiceTemplate()
.marshalSendAndReceive(
request,
new SoapActionCallback(
"http://F9M9MV1RENTAL:8088/mocksoap/GetCcNumber"));
} catch (Exception e) {
e.printStackTrace();
}
//I want here response in xml format??
System.out.println("res : "+response);
//Right now it is coming as :
//res : com.ewb.socialbanking.creditcardws.GetCcNumberResponse#514646ef
return response;
}
}
JAX-WS services return JAXB objects. If you want to marshall that object to an outputstream, you simply use the JAXB API.
Marshaller m = JAXBContext.newInstance(GetCcNumberResponse.class).createMarshaller();
m.marshal(response, System.out);
I've tried by my self, and it works. If you want to get the SOAP message, a good way to do it is using a handler at server side. The following is my handler.
package com.documentType.handler;
import java.io.IOException;
import java.util.Set;
import javax.xml.namespace.QName;
import javax.xml.soap.SOAPException;
import javax.xml.ws.handler.MessageContext;
import javax.xml.ws.handler.soap.SOAPHandler;
import javax.xml.ws.handler.soap.SOAPMessageContext;
public class TestHandler implements SOAPHandler<SOAPMessageContext> {
#Override
public void close(MessageContext arg0) {
// TODO Auto-generated method stub
}
#Override
public boolean handleFault(SOAPMessageContext arg0) {
// TODO Auto-generated method stub
return false;
}
// this method will be called twice (in and out)
#Override
public boolean handleMessage(SOAPMessageContext context) {
// true if the msg is going out
Boolean outBoundMsg = (Boolean) context.get(MessageContext.MESSAGE_OUTBOUND_PROPERTY);
try {
if (outBoundMsg) {
System.out.println("this is response");
context.getMessage().writeTo(System.out);
} else {
System.out.println("this is request");
context.getMessage().writeTo(System.out);
}
} catch (SOAPException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return true;
}
#Override
public Set<QName> getHeaders() {
// TODO Auto-generated method stub
return null;
}
}
The output in console is as the following
this is request
<S:Envelope xmlns:S="http://schemas.xmlsoap.org/soap/envelope/"><S:Header/><S:Body><ns2:echo xmlns:ns2="http://ws.documentType.com/"><arg0>yoyoyo</arg0></ns2:echo></S:Body></S:Envelope>
this is response
<S:Envelope xmlns:S="http://schemas.xmlsoap.org/soap/envelope/"><S:Body><ns2:echoResponse xmlns:ns2="http://ws.documentType.com/"><return>echo: yoyoyo</return></ns2:echoResponse></S:Body></S:Envelope>
If you have difficulty to add a handler, follow the following tutorial
http://www.mkyong.com/webservices/jax-ws/jax-ws-soap-handler-in-server-side/
http://www.mkyong.com/webservices/jax-ws/jax-ws-soap-handler-in-client-side/
http://www.mkyong.com/webservices/jax-ws/jax-ws-soap-handler-testing-for-client-and-server-side/
I have RESTEasy (JAX-RS) server with about 60 services (so far). I would like to automatically inject a custom response header to provider callers with the server build time: X-BuildTime: 20100335.1130.
Is there an easy way to do this without modifying each of my services?
I am trying to use a class that implements org.jboss.resteasy.spi.interception.PostProcessInterceptor with annotations #Provider and #ServerInterceptor, but I can't figure out how to modify the ServerResponse that is passed into my postProcess() method.
Although MessageBodyWriterInterceptor does the trick, it is better to use PostProcessInterceptor, as it will intercept responses that do not call MessageBodyWriters (such as Response.created(URI.create("/rest/justcreated")).build()).
For more info, see the official documentation.
import java.util.ArrayList;
import java.util.List;
import javax.ws.rs.core.MultivaluedMap;
import javax.ws.rs.ext.Provider;
import org.jboss.resteasy.annotations.interception.ServerInterceptor;
import org.jboss.resteasy.core.ServerResponse;
import org.jboss.resteasy.spi.interception.PostProcessInterceptor;
#Provider
#ServerInterceptor
public class MyPostProcessInterceptor implements PostProcessInterceptor {
#Override
public void postProcess(ServerResponse response) {
MultivaluedMap<String, Object> headers = response.getMetadata();
List<Object> domains = headers.get("X-BuildTime");
if (domains == null) { domains = new ArrayList<Object>(); }
domains.add("20100335.1130");
headers.put("X-BuildTime", domains);
}
}
I think using javax.servlet.Filter will be a much easier solution:
public void doFilter ( ServletRequest request, ServletResponse response, FilterChain chain ) throws IOException, ServletException {
HttpServletResponse httpResponse = (HttpServletResponse)response;
httpResponse.setHeadder(header, headerValue);
chain.doFilter(request, response);
}
configure it in web.xml for the relevant urls, and you are done.
How about using javax.ws.rs.core.Response ; this way you can set the header in the same place where you create the response-data.
#GET
#Path("/test")
#Produces(MediaType.APPLICATION_JSON)
public Response test( ){
HashMap<String,String> ret = new HashMap<String,String>();
ret.put("foo","bar");
return Response
.status(Response.Status.OK)
.entity(ret)
.header("X-say", "Hello world!")
.build();
}
You can also change header by MessageBodyInterceptors
( check the example at the end of section 30.1 )
#Provider
#ServerInterceptor
public class MyHeaderDecorator implements MessageBodyWriterInterceptor {
public void write(MessageBodyWriterContext context) throws IOException, WebApplicationException
{
context.getHeaders().add("My-Header", "custom");
context.proceed();
}
}