Why is my AJAX-call to JAVA-servlet not working - ajax

I am not getting my head around why an AJAX-POST is not working on a dynamic web project which I created. I have got a servlet which I am able to call with its url, but whenever I make an AJAX-call to it, the request in the doPost-function is empty.
I thought that the URL in the AJAX call was wrong, but none of the URLs I tried could fix the problem. I know that the doPost-function in the servlet is called when I debugged it.
The servlet looks like this:
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package com.mavenproject.mave;
import java.io.BufferedWriter;
import java.io.*;
import java.io.PrintWriter;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.persistence.*;
import java.util.*;
/**
*
* #author andfe
*/
public class DB extends HttpServlet {
/**
* Processes requests for both HTTP <code>GET</code> and <code>POST</code>
* methods.
*
* #param request servlet request
* #param response servlet response
* #throws ServletException if a servlet-specific error occurs
* #throws IOException if an I/O error occurs
*/
protected void processRequest(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
response.setContentType("text/html;charset=UTF-8");
try (PrintWriter out = response.getWriter()) {
/* TODO output your page here. You may use following sample code. */
out.println("<!DOCTYPE html>");
out.println("<html>");
out.println("<head>");
out.println("<title>Servlet DB</title>");
out.println("</head>");
out.println("<body>");
out.println("<h1>Servlet DB at " + request.getContextPath() + "</h1>");
out.println("</body>");
out.println("</html>");
}
}
// <editor-fold defaultstate="collapsed" desc="HttpServlet methods. Click on the + sign on the left to edit the code.">
/**
* Handles the HTTP <code>GET</code> method.
*
* #param request servlet request
* #param response servlet response
* #throws ServletException if a servlet-specific error occurs
* #throws IOException if an I/O error occurs
*/
#Override
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
processRequest(request, response);
}
/**
* Handles the HTTP <code>POST</code> method.
*
* #param request servlet request
* #param response servlet response
* #throws ServletException if a servlet-specific error occurs
* #throws IOException if an I/O error occurs
*/
#Override
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
processRequest(request, response);
write(request);
}
/**
* Returns a short description of the servlet.
*
* #return a String containing servlet description
*/
#Override
public String getServletInfo() {
return "Short description";
}// </editor-fold>
private void write(HttpServletRequest request) {
try (FileWriter writer = new FileWriter("C:\\Users\\andfe\\Desktop\\log.txt");
BufferedWriter bw = new BufferedWriter(writer)) {
bw.write(request.getContextPath());
} catch (IOException e) {
e.printStackTrace();
}
}
}
Here is my JavaScript:
/**
* This class is the controller for the main view for the application. It is specified as
* the "controller" of the Main view class.
*
* TODO - Replace this content of this view to suite the needs of your application.
*/
Ext.define('app.view.main.MainController', {
extend: 'Ext.app.ViewController',
alias: 'controller.main',
onItemSelected: function (sender, record) {
Ext.Msg.confirm('Confirm', 'Are you sure?', 'onConfirm', this);
},
onConfirm: function (choice) {
if (choice === 'yes') {
var xhttp = new XMLHttpRequest();
xhttp.open("POST", "/mave/DB", true);
xhttp.setRequestHeader("Content-type", "Content-Type: text/html; charset=utf-8");
xhttp.send("test");
}
}
});

Change to:
xhttp.setRequestHeader("Content-type", "text/html; charset=utf-8");

Related

Using filters to track response time in spring boot

I have implemented an API using spring boot and I want to track the response times of the different API calls (GET, POST, DELETE, PUT).
Currently I've been trying to use the following code as the filter
#Component
public class timeFilter implements Filter {
private static final Logger LOGGER = LoggerFactory.getLogger(timeFilter.class);
#Override
public void init(FilterConfig filterConfig) throws ServletException {
// empty
}
#Override
public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws IOException, ServletException {
long time = System.currentTimeMillis();
try {
chain.doFilter(req, resp);
} finally {
time = System.currentTimeMillis() - time;
LOGGER.trace("{}: {} ms ", ((HttpServletRequest) req).getRequestURI(), time);
}
}
#Override
public void destroy() {
// empty
}
}
However, this will only track the response time of the GET call that retrieves all students from my repository.
Is there a way that I can track the response time of the other calls as well as I need to plot the response time of each calls against each other on a graph. Also is there a reason why my first GET call has a response time of around 200-300 MS but any call after that has a response time of between 0-20?
In case any one finds this useful, here is one way of doing this using reactive WebFilter
import java.util.stream.Collectors;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import org.springframework.web.server.WebFilter;
import org.springframework.web.server.WebFilterChain;
import reactor.core.publisher.Mono;
#Component
public class RequestTimingFilter implements WebFilter {
private static final Logger LOGGER = LoggerFactory.getLogger(RequestTimingFilter.class);
private final boolean logParameters;
#Autowired
RequestTimingFilter(#Value("${flags.log.parameters:false}") boolean logParameters) {
this.logParameters = logParameters;
}
public Mono<Void> filter(ServerWebExchange exchange, WebFilterChain chain) {
long start = System.currentTimeMillis();
String path = exchange.getRequest().getPath().toString();
StringBuilder params = new StringBuilder();
if (this.logParameters) {
String pairs = exchange.getRequest().getQueryParams().toSingleValueMap()
.entrySet()
.stream()
.map(em -> String.format("%s=%s", em.getKey(), em.getValue()))
.collect(Collectors.joining(", "));
params.append(pairs.isEmpty() ? "" : ", ").append(pairs);
}
return chain.filter(exchange)
.doOnSuccess(v -> {
long endTime = System.currentTimeMillis();
if (LOGGER.isInfoEnabled()) {
LOGGER.info("tag={}, uri=\"{}\", time={}, unit=ms{}", "request-timing",
path, (endTime - start), params.toString());
}
});
}
}
You should do with spring's OncePerRequestFilter , which should do the work and
Make sure this component is scanned.
Note here i also have dynamic property testproject.logging.includeQueryParams which you can control if you need to include query params and same goes for headers,etc..
import java.io.IOException;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.server.ServletServerHttpRequest;
import org.springframework.stereotype.Component;
import org.springframework.web.filter.OncePerRequestFilter;
/**
* Implementation of Spring's {#link OncePerRequestFilter} to log each request
* including the URI, query String and execution time.
*/
#Component
public class RequestLoggingInterceptor extends OncePerRequestFilter {
/** {#code Logger} instance. */
private final Logger logger = LoggerFactory.getLogger(RequestLoggingInterceptor.class);
/** {#code true} if query parameters should be logged. */
private boolean includeQueryParams = true;
/** {#code true} if client address should be logged. */
private boolean includeClient = true;
/** {#code true} if request headers should be logged. */
private boolean includeHeaders = true;
#Override
protected void doFilterInternal(final HttpServletRequest request, final HttpServletResponse response, final FilterChain filterChain) throws ServletException, IOException {
final long start = System.nanoTime();
try {
filterChain.doFilter(request, response);
} finally {
if( logger.isInfoEnabled() ) {
final long end = System.nanoTime();
logger.info(buildMessage(request, end - start));
}
}
}
/**
* Builds the message to log from the specified {#code request} including
* the {#code executionTime}.
*
* #param request
* #param executionTime in nanoseconds
* #return log message
*/
private String buildMessage(final HttpServletRequest request, final long executionTime) {
final StringBuilder buffer = new StringBuilder();
buffer.append("method=").append(request.getMethod());
buffer.append(" uri=").append(request.getRequestURI());
if( includeQueryParams && request.getQueryString() != null ) {
buffer.append('?').append(request.getQueryString());
}
buffer.append(" executionTime=").append(executionTime);
return buffer.toString();
}
/**
* Sets whether to {#code include} the query parameter String when logging
* the request URI.
*
* #param include
*/
#Value("${testproject.logging.includeQueryParams:true}")
public void setIncludeQueryParams(final boolean include) {
includeQueryParams = include;
}
}

JSF PrimeFaces ajax request after logout and session invalidation

In my Spring Boot1.2.7/JSF2.2.12/PrimeFaces5.2/Tomcat 8 application I'm trying to implement redirect to login page after AJAX call on a website where /logout has been performed.
In order to do this I have added JsfRedirectStrategy:
/**
* Inspired by <a href=
* "http://stackoverflow.com/questions/10143539/jsf-2-spring-security-3-x-and-richfaces-4-redirect-to-login-page-on-session-tim">StackOverflow.com</a>
* and by <a href=http://www.icesoft.org/wiki/display/ICE/Spring+Security#SpringSecurity-Step4%3AConfigureYourSpringSecurityredirectStrategy">
* Spring Security 3 and ICEfaces 3 Tutorial</a>.
*
* #author banterCZ
*/
public class JsfRedirectStrategy implements InvalidSessionStrategy {
final static Logger logger = LoggerFactory.getLogger(JsfRedirectStrategy.class);
private static final String FACES_REQUEST_HEADER = "faces-request";
private String invalidSessionUrl;
/**
* {#inheritDoc}
*/
#Override
public void onInvalidSessionDetected(HttpServletRequest request, HttpServletResponse response)
throws IOException, ServletException {
boolean ajaxRedirect = "partial/ajax".equals(request.getHeader(FACES_REQUEST_HEADER));
if (ajaxRedirect) {
String contextPath = request.getContextPath();
String redirectUrl = contextPath + invalidSessionUrl;
logger.debug("Session expired due to ajax request, redirecting to '{}'", redirectUrl);
String ajaxRedirectXml = createAjaxRedirectXml(redirectUrl);
logger.debug("Ajax partial response to redirect: {}", ajaxRedirectXml);
response.setContentType("text/xml");
response.getWriter().write(ajaxRedirectXml);
} else {
String requestURI = getRequestUrl(request);
logger.debug(
"Session expired due to non-ajax request, starting a new session and redirect to requested url '{}'",
requestURI);
request.getSession(true);
response.sendRedirect(requestURI);
}
}
private String getRequestUrl(HttpServletRequest request) {
StringBuffer requestURL = request.getRequestURL();
String queryString = request.getQueryString();
if (StringUtils.hasText(queryString)) {
requestURL.append("?").append(queryString);
}
return requestURL.toString();
}
private String createAjaxRedirectXml(String redirectUrl) {
return new StringBuilder().append("<?xml version=\"1.0\" encoding=\"UTF-8\"?>")
.append("<partial-response><redirect url=\"").append(redirectUrl)
.append("\"></redirect></partial-response>").toString();
}
public void setInvalidSessionUrl(String invalidSessionUrl) {
this.invalidSessionUrl = invalidSessionUrl;
}
}
This is my WebSecurityConfig
#Configuration
#EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
#Autowired
private UserDetailsServiceImpl userDetailsService;
#Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userDetailsService);
}
#Override
#Bean
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}
#Override
protected void configure(HttpSecurity http) throws Exception {
// #formatter:off
http
.addFilterBefore(sessionManagementFilter(), AnonymousAuthenticationFilter.class)
.csrf().disable()
.authorizeRequests()
.antMatchers("/invite.xhtml").permitAll()
.antMatchers("/forgotpassword.xhtml").permitAll()
.antMatchers("/resetpwd.xhtml").permitAll()
.antMatchers("/admin/**").hasRole(Roles.ROLE_ADMIN.getSpringSecName())
.antMatchers("/**").authenticated()
.antMatchers("/actuator/**").permitAll()
.and()
.formLogin()
.loginPage("/login.xhtml").permitAll()
//.failureUrl("/login?error").permitAll()
.and()
.logout()
.logoutUrl("/logout")
.logoutRequestMatcher( new AntPathRequestMatcher("/logout"))
.logoutSuccessUrl("/login.xhtml")
.invalidateHttpSession(true)
.deleteCookies("JSESSIONID")
.permitAll();
http.headers().frameOptions().disable();
// #formatter:on
}
#Override
public void configure(WebSecurity web) throws Exception {
web.ignoring().antMatchers("/javax.faces.resource/**");
}
#Bean
public SessionManagementFilter sessionManagementFilter() {
SessionManagementFilter sessionManagementFilter = new SessionManagementFilter(httpSessionSecurityContextRepository());
sessionManagementFilter.setInvalidSessionStrategy(jsfRedirectStrategy());
return sessionManagementFilter;
}
public HttpSessionSecurityContextRepository httpSessionSecurityContextRepository() {
return new HttpSessionSecurityContextRepository();
}
#Bean
public JsfRedirectStrategy jsfRedirectStrategy() {
JsfRedirectStrategy jsfRedirectStrategy = new JsfRedirectStrategy();
jsfRedirectStrategy.setInvalidSessionUrl("/login.xhtml");
return jsfRedirectStrategy;
}
}
This is logout link:
<div id="LogoutContainer" class="PFTopLinks floatRight boldFont">
<h:form rendered="#{not empty request.remoteUser}">
<h:graphicImage name="main/images/pfPush.svg" />
<h:outputLink value="${pageContext.request.contextPath}/logout">
<span class="PFDarkText">Logout</span>
</h:outputLink>
</h:form>
</div>
The problem: Right now JsfRedirectStrategy.onInvalidSessionDetected is never invoked on AJAX JSF call because request.isRequestedSessionIdValid() in SessionManagementFilter.doFilter() always returns true.
There after logout I have an instance of org.apache.catalina.session.StandardSessionFacade
Whats wrong with my code ?
I have reimplemented this approach with a following code(based on this topic http://forum.primefaces.org/viewtopic.php?f=3&t=33380):
I have added AjaxTimeoutPhaseListener phase listener:
public class AjaxTimeoutPhaseListener implements PhaseListener {
private static final long serialVersionUID = 2639152532235352192L;
public static Logger logger = LoggerFactory.getLogger(AjaxTimeoutPhaseListener.class);
#Override
public void afterPhase(PhaseEvent ev) {
}
#Override
public void beforePhase(PhaseEvent ev) {
FacesContext fc = FacesUtils.getContext();
RequestContext rc = RequestContext.getCurrentInstance();
HttpServletResponse response = FacesUtils.getResponse();
HttpServletRequest request = FacesUtils.getRequest();
if (FacesUtils.getExternalContext().getUserPrincipal() == null) {
if (FacesUtils.getExternalContext().isResponseCommitted()) {
// redirect is not possible
return;
}
try {
if (((rc != null && rc.isAjaxRequest())
|| (fc != null && fc.getPartialViewContext().isPartialRequest()))
&& fc.getResponseWriter() == null && fc.getRenderKit() == null) {
response.setCharacterEncoding(request.getCharacterEncoding());
RenderKitFactory factory = (RenderKitFactory) FactoryFinder
.getFactory(FactoryFinder.RENDER_KIT_FACTORY);
RenderKit renderKit = factory.getRenderKit(fc,
fc.getApplication().getViewHandler().calculateRenderKitId(fc));
ResponseWriter responseWriter = renderKit.createResponseWriter(response.getWriter(), null,
request.getCharacterEncoding());
responseWriter = new PartialResponseWriter(responseWriter);
fc.setResponseWriter(responseWriter);
FacesUtils.redirect("/login.xhtml");
}
} catch (IOException ex) {
StringBuilder error = new StringBuilder("Redirect to the specified page '");
error.append("/login.xhtml");
error.append("' failed");
logger.error(error.toString(), ex);
throw new FacesException(ex);
}
} else {
return; // This is not a timeout case . Do nothing !
}
}
public PhaseId getPhaseId() {
return PhaseId.RESTORE_VIEW;
}
}
Also added FacesUtils class(extracted from OmniFaces lib):
public class FacesUtils {
public static Logger logger = LoggerFactory.getLogger(FacesUtils.class);
/**
* Returns the current faces context.
* <p>
* <i>Note that whenever you absolutely need this method to perform a general task, you might want to consider to
* submit a feature request to OmniFaces in order to add a new utility method which performs exactly this general
* task.</i>
* #return The current faces context.
* #see FacesContext#getCurrentInstance()
*/
public static FacesContext getContext() {
return FacesContext.getCurrentInstance();
}
/**
* Returns the HTTP servlet response.
* <p>
* <i>Note that whenever you absolutely need this method to perform a general task, you might want to consider to
* submit a feature request to OmniFaces in order to add a new utility method which performs exactly this general
* task.</i>
* #return The HTTP servlet response.
* #see ExternalContext#getResponse()
*/
public static HttpServletResponse getResponse() {
return getResponse(getContext());
}
/**
* {#inheritDoc}
* #see Faces#getResponse()
*/
public static HttpServletResponse getResponse(FacesContext context) {
return (HttpServletResponse) context.getExternalContext().getResponse();
}
/**
* Returns the HTTP servlet request.
* <p>
* <i>Note that whenever you absolutely need this method to perform a general task, you might want to consider to
* submit a feature request to OmniFaces in order to add a new utility method which performs exactly this general
* task.</i>
* #return The HTTP servlet request.
* #see ExternalContext#getRequest()
*/
public static HttpServletRequest getRequest() {
return getRequest(getContext());
}
/**
* {#inheritDoc}
* #see Faces#getRequest()
*/
public static HttpServletRequest getRequest(FacesContext context) {
return (HttpServletRequest) context.getExternalContext().getRequest();
}
/**
* Returns the current external context.
* <p>
* <i>Note that whenever you absolutely need this method to perform a general task, you might want to consider to
* submit a feature request to OmniFaces in order to add a new utility method which performs exactly this general
* task.</i>
* #return The current external context.
* #see FacesContext#getExternalContext()
*/
public static ExternalContext getExternalContext() {
return getContext().getExternalContext();
}
/**
* Returns the HTTP request context path. It's the webapp context name, with a leading slash. If the webapp runs
* on context root, then it returns an empty string.
* #return The HTTP request context path.
* #see ExternalContext#getRequestContextPath()
*/
public static String getRequestContextPath() {
return getRequestContextPath(getContext());
}
/**
* {#inheritDoc}
* #see Faces#getRequestContextPath()
*/
public static String getRequestContextPath(FacesContext context) {
return context.getExternalContext().getRequestContextPath();
}
/**
* Does a regular or ajax redirect.
*/
public static void redirect(String redirectPage) throws FacesException {
checkViewRoot(FacesUtils.getContext(), FacesUtils.getRequestContextPath());
FacesContext fc = FacesUtils.getContext();
ExternalContext ec = fc.getExternalContext();
try {
if (ec.isResponseCommitted()) {
// redirect is not possible
return;
}
// fix for renderer kit (Mojarra's and PrimeFaces's ajax redirect)
if ((RequestContext.getCurrentInstance().isAjaxRequest() || fc.getPartialViewContext().isPartialRequest())
&& fc.getResponseWriter() == null && fc.getRenderKit() == null) {
ServletResponse response = (ServletResponse) ec.getResponse();
ServletRequest request = (ServletRequest) ec.getRequest();
response.setCharacterEncoding(request.getCharacterEncoding());
RenderKitFactory factory = (RenderKitFactory) FactoryFinder
.getFactory(FactoryFinder.RENDER_KIT_FACTORY);
RenderKit renderKit = factory.getRenderKit(fc,
fc.getApplication().getViewHandler().calculateRenderKitId(fc));
ResponseWriter responseWriter = renderKit.createResponseWriter(response.getWriter(), null,
request.getCharacterEncoding());
fc.setResponseWriter(responseWriter);
}
ec.redirect(ec.getRequestContextPath() + (redirectPage != null ? redirectPage : ""));
} catch (IOException e) {
logger.error("Redirect to the specified page '" + redirectPage + "' failed");
throw new FacesException(e);
}
}
public static void checkViewRoot(FacesContext ctx, String viewId) {
if (ctx.getViewRoot() == null) {
UIViewRoot viewRoot = ctx.getApplication().getViewHandler().createView(ctx, viewId);
if (viewRoot != null) {
ctx.setViewRoot(viewRoot);
}
}
}
}
also added following lines to faces-config.xml:
<lifecycle>
<phase-listener>com.domain.AjaxTimeoutPhaseListener</phase-listener>
</lifecycle>
Now everything works fine

Unable to inject a session bean into a servlet on my bluemix app

I created a simple Java EE app in bluemix and deployed it. Then I created session bean and a servlet. I am unable to access the session bean method from Servlet.
Anybody has done this on bluemix?
here is my servlet code...
package nags.test.web;
import java.io.IOException;
import java.io.PrintWriter;
import javax.ejb.EJB;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import nags.test.ejb.NagseSessionBean;
/**
* Servlet implementation class TestServlet
*/
#WebServlet("/TestServlet")
public class TestServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
#EJB
NagseSessionBean nagsBean;
/**
* #see HttpServlet#HttpServlet()
*/
public TestServlet() {
super();
// TODO Auto-generated constructor stub
}
/**
* #see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
*/
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// TODO Auto-generated method stub
doService(request, response);
}
/**
* #see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
*/
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// TODO Auto-generated method stub
doService(request, response);
}
public void doService(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// TODO Auto-generated method stub
System.out.println("TestServlet doService Begin");
response.setContentType("text/html");
PrintWriter out = response.getWriter();
out.println("<!DOCTYPE HTML>");
out.println("<html>");
out.println("<head>");
out.println("<meta charset=\"UTF-8\">");
out.println("<title>Nags HTML from Servlet</title>");
out.println("</head>");
out.println("<body bgcolor=\"white\">");
out.println("<h1> This is Nags HTML5 PAge </h1>");
if (nagsBean == null){
System.out.println("TestServlet doService Unable to inject EJB");
}else{
System.out.println("TestServlet doService Able to inject EJB");
String helloString = nagsBean.sayHello("Nagarjun");
if (helloString == null){
out.println("<h1> No Response from Session Bean </h1>");
}else {
out.println("<h1> helloString </h1>");
}
}
out.println("</body>");
out.println("</html>");
System.out.println("TestServlet doService End");
//out.flush();
//out.close();
}
}
Your code has no errors, and trying on Bluemix works fine. I tried it using both a Stateless and a Stateful enterprise bean.
So probably there is an error with your Bean code.
To investigate the possible problem, retrieve the Bluemix logs using the "cf logs --recent" command and analyse the exception thrown.

Configuring Spring Security with Spring Boot

I am new to configuring Spring Security using Java Config. I was trying to follow this posting. However, when I run my app, I get a Basic Auth challenge on all URLs, including /. Entering the either of the userid/pass combos below do not seem to work.
My Controller:
package com.xxx.web;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
#Controller
#RequestMapping("/")
/**
* Controller to handle basic "root" URLs
*
* #author xxx
* #version 0.1.0
*/
public class RootController {
/**
* Handles '/'
* #param model
* #return
*/
#RequestMapping
public String index(Model model) {
return "index";
}
/**
* Handles '/signup'
* #param model
* #return
*/
#RequestMapping("/signup")
public String signup(Model model) {
return "signup";
}
/**
* Handles '/about'
* #param model
* #return
*/
#RequestMapping("/about")
public String about(Model model) {
return "about";
}
/**
* Handles '/login'
* #param model
* #return
*/
#RequestMapping("/login")
public String login(Model model) {
return "login";
}
/**
* Handles '/admin'
* #param model
* #return
*/
#RequestMapping("/admin")
public String admin(Model model) {
return "admin";
}
}
Not sure what else to try. Just looking for some guidance as to why this isn't working.
Update
For completeness, here is the config class:
package com.xxx.config;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.builders.WebSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
#Configuration
#EnableWebSecurity
/**
* Configures the security for the application
*
* #author XXX
* #version 0.1.0
*
*/
public class WebSecurityAppConfig extends WebSecurityConfigurerAdapter {
#Override
/**
* #see org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter#registerAuthentication(AuthenticationManagerBuilder)
*/
protected void registerAuthentication(AuthenticationManagerBuilder auth)
throws Exception {
auth
.inMemoryAuthentication()
.withUser("user") // #1
.password("password")
.roles("USER")
.and()
.withUser("admin") // #2
.password("password")
.roles("ADMIN","USER");
}
#Override
/**
* #see org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter#configure(WebSecurity)
*/
public void configure(WebSecurity web) throws Exception {
web
.ignoring()
.antMatchers("/resources/**"); // #3
}
#Override
/**
* #see org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter#configure(HttpSecurity)
*/
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/","/signup","/about").permitAll() // #4
.antMatchers("/admin/**").hasRole("ADMIN") // #6
.anyRequest().authenticated() // 7
.and()
.formLogin() // #8
.loginPage("/login") // #9
.permitAll(); // #5
}
}
And the WebApplicationInitializer:
package com.xxx.config;
import org.springframework.web.servlet.support.AbstractAnnotationConfigDispatcherServletInitializer;
/**
*
* #author XXX
* #version 0.1.0
*/
public class SpringWebMvcInitializer extends
AbstractAnnotationConfigDispatcherServletInitializer {
#Override
/**
*
*/
protected Class<?>[] getRootConfigClasses() {
return new Class[] { WebSecurityAppConfig.class };
}
#Override
/**
*
*/
protected Class<?>[] getServletConfigClasses() {
return null;
}
#Override
/**
*
*/
protected String[] getServletMappings() {
return null;
}
}
I didn't include these before because they are pretty much a copy-paste from the referenced blog posting.
The original question is probably best answered by just describing the options available. Some applications (services that only need basic HTTP authentication) can use the default settings in the actuator, others will need to specify security.* properties (see SecurityProperties for options) and/or an AuthenticationManager (for user account details). The next level of control comes from adding your own WebSecurityConfigurerAdapter, and you can see how to do that by looking at the "secure" sample in Spring Boot.

Spring exhausting inputstream of the request

I am trying to pass a String array from a Web Service to a Spring web application.
The Web Service code is :
/**
*
*/
package lnt.remote.ws;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.Properties;
import javax.jws.WebMethod;
import javax.jws.WebService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* #author 298790
*
* This class is a JAX-WS end-point implementation and contains
* method(s) to fire batch jobs pertaining to reports
*/
#WebService
public class BatchJobWS {
private static String remoteAppURL;
private static Logger log = LoggerFactory.getLogger(Constants.WS_LOGGER);
static {
try {
Properties props = new Properties();
props.load(BatchJobWS.class.getResourceAsStream("/url.properties"));
remoteAppURL = props.getProperty(Constants.REMOTE_APP_URL);
log.info("In BatchJobWS , remote app. url is {}", remoteAppURL);
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
// e.printStackTrace();
log.error("FileNotFoundException in static block of BatchJobWS", e);
} catch (IOException e) {
// TODO Auto-generated catch block
// e.printStackTrace();
log.error("IOException in static block of BatchJobWS", e);
}
}
#WebMethod
public String[] generateReportBatchJob(String... params) {
HttpURLConnection httpConn;
URL remotePayrollUrl = null;
ObjectOutputStream oos = null;
String[] returnValues = null;
log.info("In BatchJobWS.generateReportBatchJob(...),params = {}",
params);
if (params == null || params.length == 0) {
return null;
}
try {
remotePayrollUrl = new URL(remoteAppURL);
} catch (MalformedURLException e1) {
// TODO Auto-generated catch block
// e1.printStackTrace();
log.error(
"MalformedURLException in BatchJobWS.generateReportBatchJob(...)",
e1);
}
/*
* Give some thought to which exception(s) be handled and which must be
* thrown
*/
try {
httpConn = (HttpURLConnection) remotePayrollUrl.openConnection();
httpConn.setDoOutput(true);
httpConn.setUseCaches(false);
oos = new ObjectOutputStream(httpConn.getOutputStream());
log.info("Writing params to the outputstream");
oos.writeObject(params);
oos.flush();
oos.close();
ObjectInputStream ois = new ObjectInputStream(
httpConn.getInputStream());
Object returnParams = ois.readObject();
log.info("Reading params from the inputstream");
if (returnParams.getClass().isArray()) {
returnValues = (String[]) returnParams;
}
} catch (IOException e) {
// TODO Auto-generated catch block
// e.printStackTrace();
log.error("IOException in BatchJobWS.generateReportBatchJob(...)",
e);
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
// e.printStackTrace();
log.error(
"ClassNotFoundException in BatchJobWS.generateReportBatchJob(...)",
e);
}
log.info(
"Returning from BatchJobWS.generateReportBatchJob(...),returnValues = {}",
returnValues);
return returnValues;
}
}
Initially, on the web application side, I had written a plain-old servlet as shown below :
package lnt.remote;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import lnt.service.ReportService;
import lnt.utilities.BatchJobService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Controller;
import org.springframework.stereotype.Service;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
/**
* Servlet implementation class RemoteCallInterceptor
*/
public class RemoteCallInterceptor extends HttpServlet {
private static final long serialVersionUID = 1L;
private static Logger log = LoggerFactory
.getLogger(RemoteCallInterceptor.class);
/**
* #see HttpServlet#HttpServlet()
*/
public RemoteCallInterceptor() {
// super();
// TODO Auto-generated constructor stub
}
/**
* #see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse
* response)
*/
protected void doGet(HttpServletRequest request,
HttpServletResponse response) throws ServletException, IOException {
// TODO Auto-generated method stub
log.info("In Target Payroll. RemoteCallInterceptor.doGet()");
}
/**
* #see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse
* response)
*/
protected void doPost(HttpServletRequest request,
HttpServletResponse response) throws ServletException, IOException {
// TODO Auto-generated method stub
log.info(
"In Target Payroll. RemoteCallInterceptor.doPost(),reportService = {}",
reportService);
BatchJobService BatchJobService = new BatchJobService();
BatchJobService.runBatchJob(request, response);
}
}
I wrote a new class BatchJobService that calls a few existing Spring beans which , in turn, have multiple Spring beans injected using #Autowire. Hence, the code in BatchJobService(which is not a Spring-managed component) was failing with NullPointerException(asthe beans were not getting injected).
Hence, to ‘inject’ BatchJobService(thereby, injecting the beans needed in BatchJobService ) in RemoteCallInterceptor, I made the latter a Spring Controller(using #Controller) and modified the doPost(…) as shown :
package lnt.remote;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import lnt.service.ReportService;
import lnt.utilities.BatchJobService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Controller;
import org.springframework.stereotype.Service;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
/**
* Servlet implementation class RemoteCallInterceptor
*/
#Controller
public class RemoteCallInterceptor extends HttpServlet {
private static final long serialVersionUID = 1L;
private static Logger log = LoggerFactory
.getLogger(RemoteCallInterceptor.class);
#Autowired
#Qualifier("ReportService")
ReportService reportService;
/**
* #see HttpServlet#HttpServlet()
*/
public RemoteCallInterceptor() {
// super();
// TODO Auto-generated constructor stub
}
/**
* #see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse
* response)
*/
protected void doGet(HttpServletRequest request,
HttpServletResponse response) throws ServletException, IOException {
// TODO Auto-generated method stub
log.info("In Target Payroll. RemoteCallInterceptor.doGet()");
}
/**
* #see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse
* response)
*/
#RequestMapping(value = "/RemoteCallInterceptor.do", method = RequestMethod.POST)
protected void doPost(HttpServletRequest request,
HttpServletResponse response) throws ServletException, IOException {
// TODO Auto-generated method stub
log.info(
"In Target Payroll. RemoteCallInterceptor.doPost(),reportService = {}",
reportService);
BatchJobService BatchJobService = new BatchJobService();
BatchJobService.runBatchJob(request, response);
}
}
But now the issue is that the code in BatchJobService that reads the object(String array written by the Web Service) from the input stream gets an EOFException.
I suppose the #RequestMapping thing caused the input stream to be consumed - is my assumption correct ? If not, how should I retrieve the String [] params – which is neither a parameter nor an attribute, in web application? If yes, what can be the work-around?
I suspect that it's broken because the Spring MVC application is broken, and that your WS client is being sent an error response. Your BatchJobWS isn't checking the HTTP response code, and is just assuming everything's fine. It's not surprising that it gets an exception.
You need to do two things. Firstly, add an explicit response status check to BatchJobWS, e.g.
HttpURLConnection httpConn;
...
oos.writeObject(params);
oos.flush();
oos.close();
if (httpConn.getResponseCode() != 200) {
// error - throw an exception, or whatever
}
Secondly, there's no point in annotating an HttpServlet with #Controller - use one or the other, not both. Remove the extends HttpServlet and make doPost public. The protected may be what's causing the error.

Resources