Apollo Client throwing NPE when ApolloQueryCall.enqueue is called - apollo-client

I am learning GraphQL Client to Server communication using JAVA. I am using Apollo-Client now. facing issue on executing query throug java client.
My GraphQL Schema:
type Query {
bookById(id: ID): Book
}
type Book {
id: ID
name: String
pageCount: Int
author: Author
}
type Author {
id: ID
firstName: String
lastName: String
}
My Query Schema
query BookById($id: ID!) {
bookById(id: $id) {
name
}
}
I have generated Java Client code from Apollo Gradle Plugin.
Below is my client code:
public class Client {
private static final String BASE_URL = "https://localhost:8080/graphql";
private ApolloClient apolloClient;
private AtomicInteger result;
#Test
public void connectServer() throws InterruptedException {
OkHttpClient okHttpClient = new OkHttpClient.Builder()
.build();
apolloClient = ApolloClient.builder()
.serverUrl(BASE_URL)
.okHttpClient(okHttpClient)
.build();
BookByIdQuery bookByIdQuery = new BookByIdQuery("book-1");
ApolloQueryCall<BookByIdQuery.Data> query = apolloClient
.query(bookByIdQuery);
System.out.println(bookByIdQuery.queryDocument());
query.enqueue(new CallBackImpl());
Thread.currentThread().join();
}
private class CallBackImpl extends ApolloCall.Callback<BookByIdQuery.Data> {
#Override
public void onResponse(#Nonnull Response<BookByIdQuery.Data> response) {
log.info(response.data().bookById().name());
}
#Override
public void onFailure(#Nonnull ApolloException e) {
log.info("Fail:" + e.getMessage());
}
}
}
When I ran this client program it is throwing:
Exception in thread "OkHttp Dispatcher" java.lang.NullPointerException
at Client$CallBackImpl.onFailure(Client.java:61)
at com.apollographql.apollo.ApolloCall$Callback.onNetworkError(ApolloCall.java:115)
at com.apollographql.apollo.internal.RealApolloCall$1.onFailure(RealApolloCall.java:238)
at com.apollographql.apollo.internal.interceptor.ApolloCacheInterceptor$1$1.onFailure(ApolloCacheInterceptor.java:91)
at com.apollographql.apollo.internal.interceptor.ApolloParseInterceptor$1.onFailure(ApolloParseInterceptor.java:63)
at com.apollographql.apollo.internal.interceptor.ApolloServerInterceptor$1$1.onFailure(ApolloServerInterceptor.java:89)
at okhttp3.RealCall$AsyncCall.execute(RealCall.java:148)
at okhttp3.internal.NamedRunnable.run(NamedRunnable.java:32)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
at java.lang.Thread.run(Thread.java:745)
Server Side Error:
ava.lang.IllegalArgumentException: Invalid character found in method name. HTTP method names must be tokens
at org.apache.coyote.http11.Http11InputBuffer.parseRequestLine(Http11InputBuffer.java:414) ~[tomcat-embed-core-9.0.14.jar:9.0.14]
at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:294) ~[tomcat-embed-core-9.0.14.jar:9.0.14]
at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:66) [tomcat-embed-core-9.0.14.jar:9.0.14]
at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:834) [tomcat-embed-core-9.0.14.jar:9.0.14]
at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1417) [tomcat-embed-core-9.0.14.jar:9.0.14]
at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49) [tomcat-embed-core-9.0.14.jar:9.0.14]
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142) [na:1.8.0_121]
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617) [na:1.8.0_121]
at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61) [tomcat-embed-core-9.0.14.jar:9.0.14]
at java.lang.Thread.run(Thread.java:745) [na:1.8.0_121]
From insomnia client the same call is working fine on URL: https://localhost:8080/graphql:

Replaced https to http in BASE_URL.
Server was not able to understand https request.

Related

OAuth2 Spring security with Google login doesn't work

I found a really good tutorial on third-party login with Spring security in the link below,
It contains both front-end and back-end code.
https://www.callicoder.com/spring-boot-security-oauth2-social-login-part-1/
Github : https://github.com/callicoder/spring-boot-react-oauth2-social-login-demo
Everything works perfectly locally as well as in a cloud server in a normal docker container.
But if I put this code behind a reverse proxy preferably Nginx (using docker swarm) there seems to be some issue in the redirection. In my console, I'll get the authorization_request_not_found error. I have basically googled and tried everything but for some reason, it's not working. I am definitely missing something. So any help is much appreciated. The required code snippets are down below.
For example, if our domain is test.oauth.com
i) Nginx proxy's default.conf
server {
listen 443 ssl;
index index.html index.htm index.nginx-debian.html;
server_name test.oauth.com;
ssl_certificate /home/bundle_chained.crt;
ssl_certificate_key /home/private.key;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header Host $http_host;
proxy_set_header X-Forwarded-Host $server_name;
proxy_set_header X-Forwarded-Server $host;
proxy_set_header X-Forwarded-Port $server_port;
proxy_set_header Cookie $http_cookie;
access_log /var/log/nginx/reverse-access.log;
error_log /var/log/nginx/reverse-error.log;
location /login {
rewrite ^/login(.*)$ $1 break;
proxy_pass http://test-login-server:8080/;
proxy_redirect off;
}
location / {
rewrite ^/(.*)$ /$1 break;
proxy_pass http://test-react-server/;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection ‘upgrade’;
proxy_cache_bypass $http_upgrade;
}
}
server {
listen 80;
server_name test.oauth.com;
return 301 https://$host$request_uri;
}
ii) Nginx react server's default.conf
server {
listen 80;
index index.html index.htm index.nginx-debian.html;
server_name test.oauth.com;
location / {
root /usr/share/nginx/html;
index index.html index.htm;
try_files $uri $uri/ /index.html;
proxy_cache cache_zone;
proxy_cache_background_update on;
proxy_cache_lock on;
proxy_cache_use_stale error timeout http_500;
proxy_cache_valid 200 10m;
add_header X-Cached $upstream_cache_status;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root /usr/share/nginx/html;
}
}
I am using another Nginx server (test-react-server) to serve the front-end build.
iii) Application.yml of Spring
server:
forward-headers-strategy: NATIVE
spring:
datasource:
url: jdbc:mysql://127.0.0.1:3306/spring_social?createDatabaseIfNotExist=true
username: <username>
password: <password>
jpa:
show-sql: true
hibernate:
ddl-auto: update
naming-strategy: org.hibernate.cfg.ImprovedNamingStrategy
properties:
hibernate:
dialect: org.hibernate.dialect.MySQL5InnoDBDialect
security:
oauth2:
client:
registration:
google:
clientId: <google-client-id>
clientSecret: <google-client-secret>
redirectUri: "{baseUrl}/login/oauth2/callback/{registrationId}"
scope:
- email
- profile
facebook:
clientId: <facebook-client-id>
clientSecret: <facebook-client-secret>
redirectUri: "{baseUrl}/login/oauth2/callback/{registrationId}"
scope:
- email
- public_profile
github:
clientId: <github-client-id>
clientSecret: <github-client-secret>
redirectUri: "{baseUrl}/login/oauth2/callback/{registrationId}"
scope:
- user:email
- read:user
provider:
facebook:
authorizationUri: https://www.facebook.com/v3.0/dialog/oauth
tokenUri: https://graph.facebook.com/v3.0/oauth/access_token
userInfoUri: https://graph.facebook.com/v3.0/me?fields=id,first_name,middle_name,last_name,name,email,verified,is_verified,picture.width(250).height(250)
app:
auth:
tokenSecret: 04ca023b39512e46d0c2cf4b48d5aac61d34302994c87ed4eff225dcf3b0a218739f3897051a057f9b846a69ea2927a587044164b7bae5e1306219d50b588cb1
tokenExpirationMsec: 864000000
cors:
#allowedOrigins: http://localhost:3000
allowedOrigins: https://test.oauth.com,https://test.oauth.com/login
oauth2:
authorizedRedirectUris:
#- http://localhost:3000/oauth2/redirect
- https://test.oauth.com/oauth2/redirect
iv) Front-end's package.json
{
"name": "react-social",
"version": "0.1.0",
"private": true,
"homepage": "http://test-react-server",
"dependencies": {
"react": "^16.5.2",
"react-dom": "^16.5.2",
"react-router-dom": "^4.3.1",
"react-s-alert": "^1.4.1",
"react-scripts": "1.1.5"
},
"scripts": {
"start": "react-scripts start",
"build": "react-scripts build",
"test": "react-scripts test --env=jsdom",
"eject": "react-scripts eject"
}
}
v) Front-end's index.js
export const API_BASE_URL = 'https://test.oauth.com/login';
export const ACCESS_TOKEN = 'accessToken';
export const OAUTH2_REDIRECT_URI = 'https://test.oauth.com/oauth2/redirect'
export const GOOGLE_AUTH_URL = API_BASE_URL + '/oauth2/authorize/google?redirect_uri=' + OAUTH2_REDIRECT_URI;
export const FACEBOOK_AUTH_URL = API_BASE_URL + '/oauth2/authorize/facebook?redirect_uri=' + OAUTH2_REDIRECT_URI;
export const GITHUB_AUTH_URL = API_BASE_URL + '/oauth2/authorize/github?redirect_uri=' + OAUTH2_REDIRECT_URI;
vi) Stack trace of error
org.springframework.security.oauth2.core.OAuth2AuthenticationException: [authorization_request_not_found]
at org.springframework.security.oauth2.client.web.OAuth2LoginAuthenticationFilter.attemptAuthentication(OAuth2LoginAuthenticationFilter.java:170)
at org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter.doFilter(AbstractAuthenticationProcessingFilter.java:222)
at org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter.doFilter(AbstractAuthenticationProcessingFilter.java:212)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336)
at org.springframework.security.oauth2.client.web.OAuth2AuthorizationRequestRedirectFilter.doFilterInternal(OAuth2AuthorizationRequestRedirectFilter.java:178)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336)
at org.springframework.security.web.authentication.logout.LogoutFilter.doFilter(LogoutFilter.java:103)
at org.springframework.security.web.authentication.logout.LogoutFilter.doFilter(LogoutFilter.java:89)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336)
at org.springframework.web.filter.CorsFilter.doFilterInternal(CorsFilter.java:91)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336)
at org.springframework.security.web.header.HeaderWriterFilter.doHeadersAfter(HeaderWriterFilter.java:90)
at org.springframework.security.web.header.HeaderWriterFilter.doFilterInternal(HeaderWriterFilter.java:75)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336)
at org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:110)
at org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:80)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336)
at org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter.doFilterInternal(WebAsyncManagerIntegrationFilter.java:55)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336)
at org.springframework.security.web.FilterChainProxy.doFilterInternal(FilterChainProxy.java:211)
at org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:183)
at org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:358)
at org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:271)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)
at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:100)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)
at org.springframework.web.filter.FormContentFilter.doFilterInternal(FormContentFilter.java:93)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)
at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:201)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:197)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:97)
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:540)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:135)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:92)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:78)
at org.apache.catalina.valves.RemoteIpValve.invoke(RemoteIpValve.java:769)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:357)
at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:382)
at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:65)
at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:893)
at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1726)
at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49)
at org.apache.tomcat.util.threads.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1191)
at org.apache.tomcat.util.threads.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:659)
at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
at java.base/java.lang.Thread.run(Thread.java:833)
I dumped the stack trace in OAuth2AuthenticationFailureHandler class.
Update:
For anyone stumbling upon the same issue. I was not able to solve this issue using the above cookie-based configuration. However, I understood why it was not working.
i) User clicks on the sign-in with google. At this time the OAuth2 state will be saved in the cookie.
ii) User will be redirected to the google login page with the appropriate client id and client secret in the URL which the backend will construct
iii) After the user enters the credentials and the sign-in is successful, google will redirect the browser to the redirect-URI provided by the backend in step 1.
iv) Now spring will match the initial OAuth2 request with the data sent by google.
In our case, it tries to get from the cookie. But for some reason, it won't get the cookie that it stored initially which will result in an [authorization_request_not_found] error.
Also if the client explicitly disables cookies in the browser then the above implementation wont work.
So I changed the above configuration from cookie-based implementation to DB-based implementation. This way I can have any amount of backend servers running behind the proxy since the DB will be shared between all the servers.
WebSecurityConfig.java
#SuppressWarnings("deprecation")
#Configuration
#EnableWebSecurity
#EnableGlobalMethodSecurity(prePostEnabled = true)
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
// other config
#Bean
public DBOAuth2AuthorizationRequestRepository dbAuthorizationRequestRepository() {
return new DBOAuth2AuthorizationRequestRepository();
}
// other config
#Override
protected void configure(HttpSecurity http) throws Exception {
// other config
http.authorizationRequestRepository(dbAuthorizationRequestRepository())
// other cofig
}
}
DBOAuth2AuthorizationRequestRepository.java
public class DBOAuth2AuthorizationRequestRepository implements
AuthorizationRequestRepository<OAuth2AuthorizationRequest> {
#Autowired
public OauthStateRepository oauthStateRepository;
#Override
public OAuth2AuthorizationRequest loadAuthorizationRequest(HttpServletRequest httpServletRequest) {
String state = httpServletRequest.getParameter("state");
OauthState oauthState = oauthStateRepository.findOauthStateByState(state);
return deserialize(oauthState.getSerializedValue(), OAuth2AuthorizationRequest.class);
}
#Override
public void saveAuthorizationRequest(OAuth2AuthorizationRequest oAuth2AuthorizationRequest, HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) {
String id = Generators.timeBasedGenerator().generate().toString();
BigInteger timeStamp = BigInteger.valueOf(System.currentTimeMillis());
oauthStateRepository.saveState(id, httpServletRequest.getSession().getId(), serialize(oAuth2AuthorizationRequest), httpServletRequest.getParameter("redirect_uri"), oAuth2AuthorizationRequest.getState() ,timeStamp);
}
#Override
public OAuth2AuthorizationRequest removeAuthorizationRequest(HttpServletRequest httpServletRequest) {
return this.loadAuthorizationRequest(httpServletRequest);
}
public static String serialize(Object object) {
return Base64.getUrlEncoder()
.encodeToString(SerializationUtils.serialize(object));
}
public static <T> T deserialize(String value, Class<T> cls) {
return cls.cast(SerializationUtils.deserialize(
Base64.getUrlDecoder().decode(value)));
}
}
OauthState.java
#Entity
#Getter
#Setter
#NoArgsConstructor
#AllArgsConstructor
public class OauthState {
#Id
private String id;
private String sessionId;
#Column(columnDefinition = "TEXT")
private String serializedValue;
private String redirectUri;
private String state;
#Column(columnDefinition = "bigint default 0")
private BigInteger timestamp;
}
OauthStateRepository.java
#Repository
public interface OauthStateRepository extends JpaRepository<OauthState, Integer> {
#Query(value = "SELECT id, redirect_uri, serialized_value , session_id , state, timestamp FROM oauth_state WHERE state = ?1", nativeQuery = true)
OauthState findOauthStateByState(String state);
#Modifying
#Transactional
#Query(value = "INSERT INTO oauth_state (id, redirect_uri, serialized_value, session_id, state, timestamp) VALUES (?1,?2,?3,?4,?5,?6)", nativeQuery = true)
void saveState(String id, String redirect_uri, String serialized_value, String session_id, String state ,BigInteger timestamp);
#Modifying
#Transactional
#Query(value = "DELETE FROM oauth_state WHERE state = ?1", nativeQuery = true)
void deleteOauthStateByState(String id);
#Modifying
#Transactional
#Query(value = "DELETE FROM oauth_state WHERE timestamp between 0 and ?1", nativeQuery = true)
void deleteOauthStateByTimeStamp(BigInteger timeStamp);
}
Using the above configuration Spring will be able to successfully store and retrieve the OAuth2 state data whenever it's required. You have to make sure that Invalid state data won't be stored in the table. For that, you can use the scheduler to clean up invalid data from the OAuth2 state table every day or so.

What is correct way to make AJAX call in Spring Boot web Thymeleaf application Getting getOutputStream() has already been called for this response

I am working on Spring boot based web application and using Thymeleaf on front end. I have a requirement to make a AJAX call, POST the data and on-success display data returned from the AJAX call.
below is the AJAX call to call the Controller method
var myObject = new Object();
myObject.acctTypeValue = 22;
myObject.amtBalance = "121334";
myObject.custNo="12121";
myObject.userId="2345rest";
$.ajax({
url : '/testDocWeb/forwardToCallingSystem',
type :'POST',
data : myObject,
dataType:'html',
cache: false,
timeout: 600000,
success : function(data) {
alert('Data: '+JSON.stringify(data));
},
error : function(request,error)
{
alert("Error : "+JSON.stringify(request));
}
});
and below is the Spring MVC controller:-
#PostMapping(path="/forwardToCallingSystem")
public #ResponseBody DummuyResponse forwardToCallingSystem(#ModelAttribute DummyInput dummyInput,Model model, HttpServletRequest request) {
log.info("Inside forwardToCallingSystem method." );
DummuyResponse dummyResponse = new DummuyResponse ();
dummyResponse .setDocId("756");
dummyResponse .setReasonCode('0');
dummyResponse .setReturnCode(100);
dummyResponse .setStatusCode(200);
return dummyResponse ;
}
and below is the Model object which I am returning :-
#Data
#JsonIgnoreProperties(ignoreUnknown = true)
public class DummyResponse implements Serializable {
private static final long serialVersionUID = -8191562770215698813L;
private int statusCode;
private char reasonCode;
private int returnCode;
private String docId;
}
I am not sure what is wrong but I am getting the below error on making that AJAX call:-
[ERROR]~2019-06-12-10.32.54.030CDT~~~~~~ o.a.c.c.C.[.[localhost] Exception Processing ErrorPage[errorCode=0, location=/error]
org.springframework.web.util.NestedServletException: Request processing failed; nested exception is java.lang.IllegalStateException: getOutputStream() has already been called for this response
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1013)
at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:908)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:660)
at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:882)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:741)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:231)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
at org.apache.catalina.core.ApplicationDispatcher.invoke(ApplicationDispatcher.java:712)
at org.apache.catalina.core.ApplicationDispatcher.doInclude(ApplicationDispatcher.java:580)
at org.apache.catalina.core.ApplicationDispatcher.include(ApplicationDispatcher.java:516)
at org.apache.catalina.core.StandardHostValve.custom(StandardHostValve.java:388)
at org.apache.catalina.core.StandardHostValve.status(StandardHostValve.java:253)
at org.apache.catalina.core.StandardHostValve.throwable(StandardHostValve.java:348)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:173)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:92)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:74)
at net.rakugakibox.spring.boot.logback.access.tomcat.LogbackAccessTomcatValve.invoke(LogbackAccessTomcatValve.java:91)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:343)
at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:408)
at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:66)
at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:834)
at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1415)
at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
at java.lang.Thread.run(Thread.java:745)
Caused by: java.lang.IllegalStateException: getOutputStream() has already been called for this response
I am getting issue only on making AJAX call form Thymeleaf web page for normal Spring MVC its working fine .Any help will be appreciated
In your ajax request you are using dataType:'html', But from your controller, you are returning back an Object, According to jQuery’s Ajax-Related Methods Description
// The type of data we expect back
dataType : "html"
Update your ajax request to
$.ajax({
url : '/testDocWeb/forwardToCallingSystem',
type :'POST',
data : myObject,
cache: false,
timeout: 600000,
success : function(data) {
alert('Data: ' + JSON.stringify(data));
},
error : function(request,error) {
alert("Error : " + JSON.stringify(request));
}
});
Also, this Post can be helpful.

download Document object using spring mvc without jsp

I am trying to create pdf file using POJO and download it using spring mvc.i have got the Document object but can not download the file. it gives error "could not find convertor".
#RequestMapping(value = "/downloadPDF", method = RequestMethod.GET)
public Document downloadPDF() throws FileNotFoundException, DocumentException {
// create some sample data
List<EmployeeInfo> employeeList = new ArrayList<EmployeeInfo>();
employeeList.add(new EmployeeInfo("1", "Anish", "surat"));
return downloadPDFService.createPDF(employeeList);
how can i download this file.
please provide answer
public Document createPDF( List<EmployeeInfo> employeeList) throws FileNotFoundException, DocumentException {
Document document = new Document();
PdfWriter writer = PdfWriter.getInstance(document, new FileOutputStream("AddTableExample.pdf"));
document.open();
PdfPTable table = new PdfPTable(3);
table.setWidthPercentage(100); //Width 100%
table.setSpacingBefore(10f); //Space before table
table.setSpacingAfter(10f); //Space after table
PdfPCell cell = new PdfPCell();
cell.setBackgroundColor(BaseColor.BLUE);
cell.setPadding(5);
Font font = FontFactory.getFont(FontFactory.HELVETICA);
font.setColor(BaseColor.WHITE);
cell.setPhrase(new Phrase("Id", font));
table.addCell(cell);
cell.setPhrase(new Phrase("Name", font));
table.addCell(cell);
cell.setPhrase(new Phrase("Address", font));
table.addCell(cell);
for (EmployeeInfo aBook : employeeList) {
table.addCell(aBook.getEmpId());
table.addCell(aBook.getEmpName());
table.addCell(aBook.getEmpAddress());
}
document.add(table);
document.close();
writer.close();
return document;
}
this is a view creator.next is stack trace
HTTP Status 500 - Request processing failed; nested exception is java.lang.IllegalArgumentException:
No converter found for return value of type: class com.itextpdf.text.Document
org.springframework.web.util.NestedServletException: Request processing failed; nested exception is java.lang.IllegalArgumentException: No converter found for return value of type: class com.itextpdf.text.Document
org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:982)
org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:861)
javax.servlet.http.HttpServlet.service(HttpServlet.java:622)
org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:846)
javax.servlet.http.HttpServlet.service(HttpServlet.java:729)
org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)
root cause
java.lang.IllegalArgumentException: No converter found for return value of type: class com.itextpdf.text.Document
org.springframework.web.servlet.mvc.method.annotation.AbstractMessageConverterMethodProcessor.writeWithMessageConverters(AbstractMessageConverterMethodProcessor.java:178)
org.springframework.web.servlet.mvc.method.annotation.AbstractMessageConverterMethodProcessor.writeWithMessageConverters(AbstractMessageConverterMethodProcessor.java:153)
org.springframework.web.servlet.mvc.method.annotation.RequestResponseBodyMethodProcessor.handleReturnValue(RequestResponseBodyMethodProcessor.java:165)
org.springframework.web.method.support.HandlerMethodReturnValueHandlerComposite.handleReturnValue(HandlerMethodReturnValueHandlerComposite.java:80)
org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:126)
org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:814)
org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:737)
org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:85)
org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:959)
org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:893)
org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:970)
org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:861)
javax.servlet.http.HttpServlet.service(HttpServlet.java:622)
org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:846)
javax.servlet.http.HttpServlet.service(HttpServlet.java:729)
org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)
Though you don't want jsp, you still can use ModelAndView.
Change your DownloadPDFService as below.
#Component
public class DownloadPDFService extends AbstractPdfView {
#Override
protected void buildPdfDocument(Map<String, Object> model, Document doc,
PdfWriter writer, HttpServletRequest req, HttpServletResponse resp)
throws Exception {
// Retrieve your model as below
List<EmployeeInfo> employeeList = (List<EmployeeInfo>) model.get("employeeList");
// continue your document build logic
}
}
Change your controller as below
#RequestMapping(value = "/downloadPDF", method = RequestMethod.GET)
public Document downloadPDF() throws FileNotFoundException, DocumentException {
// create some sample data
List<EmployeeInfo> employeeList = new ArrayList<EmployeeInfo>();
employeeList.add(new EmployeeInfo("1", "Anish", "surat"));
return new ModelAndView("pdfView", "employeeList", employeeList);
}
Add below views configuration in views.properties
pdfView.(class)= YourpackageName.DownloadPDFService
Configure a new ResourceBundleViewResolver for above "views" properties.

Response Error 500 in Spring (HttpStatus field null pointer)

I have build a rest web service using spring. I am getting 500 server error when the service is called.
Controller class :
#RequestMapping(value = "/wordlist", method = RequestMethod.GET)
public ResponseEntity getList(#RequestHeader("wordid") int wordId) {
ResponseList responseObejct = wordService.getList(wordId);
return ResponseEntity.status(responseObejct.getStatusCode()).body(responseObejct.getResponseWordList());
}
DaoImplementation :
String listHql = "from Word where wordId > ? or wordId = ?";
Query query = session.createQuery(listHql);
query.setParameter(0, wordId);
query.setParameter(1, wordId);
query.setMaxResults(30);
if(query.list().size()>0){
response.setStatusCode(HttpStatus.OK);
response.setResponseWordList((ArrayList<Word>)query.list());
} else {
response.setStatusCode(HttpStatus.NOT_FOUND);
}
session.getTransaction().commit();
ResponseList.java (for response)
public class ResponseList {
private ArrayList<Word> responseWordList;
private HttpStatus statusCode ;
public ArrayList<Word> getResponseWordList() {
return responseWordList;
}
public void setResponseWordList(ArrayList<Word> responseWordList) {
this.responseWordList = responseWordList;
}
public HttpStatus getStatusCode() {
return statusCode;
}
public void setStatusCode(HttpStatus statusCode) {
this.statusCode = statusCode;
}
}
Error is:
ava.lang.IllegalArgumentException: Can not set final org.springframework.http.HttpStatus field
org.springframework.http.ResponseEntity.statusCode to java.util.ArrayList
sun.reflect.UnsafeFieldAccessorImpl.throwSetIllegalArgumentException(UnsafeFieldAccessorImpl.java:167)
sun.reflect.UnsafeFieldAccessorImpl.throwSetIllegalArgumentException(UnsafeFieldAccessorImpl.java:171)
sun.reflect.UnsafeFieldAccessorImpl.ensureObj(UnsafeFieldAccessorImpl.java:58)
sun.reflect.UnsafeQualifiedObjectFieldAccessorImpl.get(UnsafeQualifiedObjectFieldAccessorImpl.java:38)
java.lang.reflect.Field.get(Field.java:393)
com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$1.write(ReflectiveTypeAdapterFactory.java:86)
com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$Adapter.write(ReflectiveTypeAdapterFactory.java:195)
com.google.gson.Gson.toJson(Gson.java:586)
com.google.gson.Gson.toJson(Gson.java:565)
org.springframework.http.converter.json.GsonHttpMessageConverter.writeInternal(GsonHttpMessageConverter.java:199)
org.springframework.http.converter.AbstractGenericHttpMessageConverter.write(AbstractGenericHttpMessageConverter.java:100)
org.springframework.web.servlet.mvc.method.annotation.AbstractMessageConverterMethodProcessor.writeWithMessageConverters(AbstractMessageConverterMethodProcessor.java:222)
org.springframework.web.servlet.mvc.method.annotation.HttpEntityMethodProcessor.handleReturnValue(HttpEntityMethodProcessor.java:183)
org.springframework.web.method.support.HandlerMethodReturnValueHandlerComposite.handleReturnValue(HandlerMethodReturnValueHandlerComposite.java:80)
org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:126)
org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:817)
org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:731)
org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:85)
org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:959)
org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:893)
org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:968)
org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:859)
javax.servlet.http.HttpServlet.service(HttpServlet.java:621)
org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:844)
javax.servlet.http.HttpServlet.service(HttpServlet.java:728)
org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:51)
I cannot understand why the error is coming. Please help.
The way you are calling ResponseEntity.status() is not valid.
It says
The method status(HttpStatus) is undefined for the type
ResponseEntity
To fix this try returning a ResponseEntity from your controller method like :
#RequestMapping(value = "/wordlist", method = RequestMethod.GET)
public ResponseEntity<ResponseList> getList(#RequestHeader("wordid") int wordId) {
ResponseList responseObejct = wordService.getList(wordId);
ResponseEntity<ResponseList> responseEntity = new ResponseEntity<>(responseObejct, HttpStatus.OK);
return responseEntity;
}
I ran into the same issue, and it turned out that this was fixed in Spring 4.3.1.
However, I cannot find a JIRA issue for that. Maybe it is a side-effect on another fix.
If you still have the problem (or if anyone else steps into this), please try again with 4.3.1 or higher.

HTTP Status 500 - Request processing failed; nested exception is java.lang.IllegalStateException

I am working on a Spring MVC application and have an issue with the validation. I need to create an user and it is a 2 step process(meaning 2 jsps with the same controller). The jsps have 2 different commandNames. So when I created the validator for the first model and initialize it, the first page loads fine. For testing, I am not using an if condition, but forwarding to next page. I get an error as the controller tries to load the validator with the current commandName object and it fails.
When I enter the url http://ip:port/data, the page loads as there is no validation, it is just initial load
When I try to submit the page without entering the firstName and submit, the method #RequestMapping(value = "/user") is called and the the next page 2 is supposed to be loaded. But the page 2 fails.
binder.getTarget() prints UserData the first time which is right
binder.getTarget() prints userinfo the 2nd time, when the next page is loading and it fails with the error
StackTrace:
HTTP Status 500 - Request processing failed; nested exception is java.lang.IllegalStateException: Invalid target for Validator [.validator.UserDataValidator#4366febc]: .model.UserInfo#4e3a061b
type Exception report
message Request processing failed; nested exception is java.lang.IllegalStateException: Invalid target for Validator [.validator.UserDataValidator#4366febc]: .model.UserInfo#4e3a061b
description The server encountered an internal error that prevented it from fulfilling this request.
exception
org.springframework.web.util.NestedServletException: Request processing failed; nested exception is java.lang.IllegalStateException: Invalid target for Validator [.validator.UserDataValidator#4366febc]: .model.UserInfo#4e3a061b
org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:978)
org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:868)
javax.servlet.http.HttpServlet.service(HttpServlet.java:648)
org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:842)
javax.servlet.http.HttpServlet.service(HttpServlet.java:729)
org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)
org.springframework.web.filter.HiddenHttpMethodFilter.doFilterInternal(HiddenHttpMethodFilter.java:77)
org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:85)
org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
root cause
java.lang.IllegalStateException: Invalid target for Validator [.validator.UserDataValidator#4366febc]: .model.UserInfo#4e3a061b
org.springframework.validation.DataBinder.assertValidators(DataBinder.java:516)
org.springframework.validation.DataBinder.setValidator(DataBinder.java:507)
.controller.AccountDataController.initBinder(AccountDataController.java:65)
sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
java.lang.reflect.Method.invoke(Method.java:606)
org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:221)
org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:137)
org.springframework.web.method.annotation.InitBinderDataBinderFactory.initBinder(InitBinderDataBinderFactory.java:62)
org.springframework.web.bind.support.DefaultDataBinderFactory.createBinder(DefaultDataBinderFactory.java:53)
org.springframework.web.method.annotation.ModelFactory.updateBindingResult(ModelFactory.java:251)
Any suggestions on how to handle this would be helpful. Is there a way to make this work - having 2 different commandNames and trying to validate using one controller or do I need to update the commandName to one object and that object has all the classes inside it.
e.g.
class Parent{
UserData UserData;
UserInfo userInfo;
getter & setter
}
My Controller:
#Controller
#SessionAttributes("userData")
public class AController {
#Autowired
#Qualifier("userDataValidator")
private Validator validator;
#InitBinder
private void initBinder(WebDataBinder binder) {
System.out.println("getTarget: "+binder.getTarget()); ------------
binder.setValidator(validator);
}
#RequestMapping(value = "/data", method = RequestMethod.GET)
public String initForm(Model model){
UserData userData = new UserData();
model.addAttribute("userData", userData);
return "page1";
}//
#RequestMapping(value = "/user", method=RequestMethod.POST )
public String details(Model model, #Validated UserData userData, BindingResult result) {
*****
model.addAttribute("userinfo", userinfo);
return "page2";
}//
**EDIT**
#RequestMapping(value = "/create", method=RequestMethod.POST )
*****************
public String create(Model model, Userinfo userinfo, UserData userData) {
*********************user creation
}
**EDIT**
}
My JSPs
page1.jsp
<form:form method="POST" action="user" commandName="userData">
<form:label path="firstName"><b>Name</b></form:label> <br />
<form:input class="formLabel" path="firstName" />
****
</form>
page2.jsp
<form:form method="POST" action="create" commandName="userinfo">
***********fields
</form>
My validator
public class UserDataValidator implements Validator{
public boolean supports(Class<?> paramClass) {
return UserData.class.equals(paramClass);
}
public void validate(Object obj, Errors errors) {
ValidationUtils.rejectIfEmptyOrWhitespace(errors, "firstName", "valid.firstName");
}
}
My Model
UserData.java
public class UserData {
String firstName;
getter & setter for firstName
}
Let me know if any more details are needed. Thanks.

Resources