Httpclien 4 gzip Post-Data - http

i'm using httpclient 4. When i use
new DecompressingHttpClient(client).execute(method)
the client acccepts gzip and decompresses if the server sends gzip.
But how can i archieve that the client sends it's data gzipped?

HttpClient 4.3 APIs:
HttpEntity entity = EntityBuilder.create()
.setText("some text")
.setContentType(ContentType.TEXT_PLAIN)
.gzipCompress()
.build();
HttpClient 4.2 APIs:
HttpEntity entity = new GzipCompressingEntity(
new StringEntity("some text", ContentType.TEXT_PLAIN));
GzipCompressingEntity implementation:
public class GzipCompressingEntity extends HttpEntityWrapper {
private static final String GZIP_CODEC = "gzip";
public GzipCompressingEntity(final HttpEntity entity) {
super(entity);
}
#Override
public Header getContentEncoding() {
return new BasicHeader(HTTP.CONTENT_ENCODING, GZIP_CODEC);
}
#Override
public long getContentLength() {
return -1;
}
#Override
public boolean isChunked() {
// force content chunking
return true;
}
#Override
public InputStream getContent() throws IOException {
throw new UnsupportedOperationException();
}
#Override
public void writeTo(final OutputStream outstream) throws IOException {
final GZIPOutputStream gzip = new GZIPOutputStream(outstream);
try {
wrappedEntity.writeTo(gzip);
} finally {
gzip.close();
}
}
}

Related

excelViewResolver not working when using java based configuration with spring mvc 4

I have the requirement to display a document in excel format in my spring mvc application. I have added excelViewResolver to my AppConfig but unable to process the excel file. Please help.
Following is the AppConfig class
#Configuration
#EnableWebMvc
#ComponentScan(basePackages = "com.testapps.myapps")
public class AppConfig extends WebMvcConfigurerAdapter {
private static final String autowire = null;
/*
* Configure ContentNegotiationManager
*/
#Override
public void configureContentNegotiation(ContentNegotiationConfigurer configurer) {
configurer.ignoreAcceptHeader(true).defaultContentType(
MediaType.TEXT_HTML);
}
/*
* Configure ContentNegotiatingViewResolver
*/
#Bean
public ViewResolver contentNegotiatingViewResolver(ContentNegotiationManager manager) {
ContentNegotiatingViewResolver resolver = new ContentNegotiatingViewResolver();
resolver.setContentNegotiationManager(manager);
// Define all possible view resolvers
List<ViewResolver> resolvers = new ArrayList<ViewResolver>();
resolvers.add(jspViewResolver());
resolvers.add(excelViewResolver());
resolver.setViewResolvers(resolvers);
return resolver;
}
/*
* Configure View resolver to provide XLS output using Apache POI library to
* generate XLS output for an object content
*/
#Bean(name="excelView")
public ViewResolver excelViewResolver() {
System.out.println("inside view resolver for excel");
return new ExcelViewResolver();
}
/*
* Configure View resolver to provide HTML output This is the default format
* in absence of any type suffix.
*/
#Bean
public ViewResolver jspViewResolver() {
InternalResourceViewResolver viewResolver = new InternalResourceViewResolver();
viewResolver.setViewClass(JstlView.class);
viewResolver.setPrefix("/WEB-INF/views/");
viewResolver.setSuffix(".jsp");
return viewResolver;
}
#Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/resources/**").addResourceLocations("/resources/");
}
#Bean(name = "multipartResolver")
public StandardServletMultipartResolver resolver() {
return new StandardServletMultipartResolver();
}
}
WebAppInitializer.java
public class WebAppInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {
#Override
protected Class<?>[] getRootConfigClasses() {
return new Class[] { AppConfig.class };
}
#Override
protected Class<?>[] getServletConfigClasses() {
return null;
}
#Override
protected String[] getServletMappings() {
return new String[] { "*.html" };
}
#Override
protected void customizeRegistration(ServletRegistration.Dynamic registration) {
registration.setMultipartConfig(getMultipartConfigElement());
}
private MultipartConfigElement getMultipartConfigElement() {
MultipartConfigElement multipartConfigElement = new MultipartConfigElement( LOCATION, MAX_FILE_SIZE, MAX_REQUEST_SIZE, FILE_SIZE_THRESHOLD);
return multipartConfigElement;
}
private static final String LOCATION = "C:/TESTdevelopments/files/"; // Temporary location where files will be stored
private static final long MAX_FILE_SIZE = 5242880; // 5MB : Max file size.
// Beyond that size spring will throw exception.
private static final long MAX_REQUEST_SIZE = 20971520; // 20MB : Total request size containing Multi part.
private static final int FILE_SIZE_THRESHOLD = 0; // Size threshold after which files will be written to disk
}
ExcelBuilder.java
public class ExcelBuilder extends AbstractXlsxView {
private static final DateFormat DATE_FORMAT = DateFormat.getDateInstance(DateFormat.SHORT);
#Override
protected void buildExcelDocument(Map<String, Object> model,
Workbook workbook,
HttpServletRequest request,
HttpServletResponse response) throws Exception {
// change the file name
response.setHeader("Content-Disposition", "attachment; filename=\"my-xlsx-file.xlsx\"");
#SuppressWarnings("unchecked")
List<Course> courses = (List<Course>) model.get("courses");
// create excel xls sheet
Sheet sheet = workbook.createSheet("Spring MVC AbstractXlsxView");
// create header row
Row header = sheet.createRow(0);
header.createCell(0).setCellValue("ID");
header.createCell(1).setCellValue("Name");
header.createCell(2).setCellValue("Date");
// Create data cells
int rowCount = 1;
for (Course course : courses){
Row courseRow = sheet.createRow(rowCount++);
courseRow.createCell(0).setCellValue(course.getId());
courseRow.createCell(1).setCellValue(course.getName());
courseRow.createCell(2).setCellValue(DATE_FORMAT.format(course.getDate()));
}
}
}
ExcelViewResolver.java
public class ExcelViewResolver implements ViewResolver{
#Override
public View resolveViewName(String viewName, Locale locale) throws Exception {
ExcelBuilder view = new ExcelBuilder();
return view;
}
}
and finally controller class mapping...
#RequestMapping(value = "/downloadExcel.html", method = RequestMethod.GET)
public ModelAndView downloadExcel() {
// create some sample data
List<courseRecordParams> reports = courseRegisterService.generateReportsGeneral();
// return a view which will be resolved by an excel view resolver
return new ModelAndView("excelView", "reports", reports);
}
The problem is I am not able to view the excel file. Its generating a file not found error as in JBWEB000124: The requested resource is not available. since it tries to open a nonexisting jsp.
Please help.
Thanks in advance.
Found a solution to this problem.
#Override
public void configureContentNegotiation(ContentNegotiationConfigurer configurer) {
configurer
.favorPathExtension(true)
.favorParameter(false)
.ignoreAcceptHeader(true)
.useJaf(false)
.defaultContentType(MediaType.APPLICATION_JSON);
}
Also, I removed the excelviewresolver which was unnecessary since this is already handled by multipartviewresolver.
After this the excel file was getting generated without any problem.

Multiple Query Params with Asyncronous Call Retrofit

UPDATE:
I have learned what I am looking to do is to use the Async within Retrofit with multiple queries too. I have updated my code, but I cannot get the async with the queries.
I am using Retrofit to make my data calls to a movie database and need to change the sort order depending on user settings. I am not clear how I could add this functionality to my interface.
sort_by=highest_rating.desc
or
sort_by=popularity.desc
Interface:
public interface MovieDatabaseApiCient {
#GET("/3/discover/movie")
void getData(#Query("api_key") String apiKey, #Query("sort_by") String sortByValue, Callback<MovieDbModel> response);
}
UPDATED API INTERFACE:
public interface MovieDatabaseApiCient {
#GET("/3/discover/movie?sort_by=popularity.desc&api_key=xxxxxxx")
void getMoviesByPopularityDesc(Callback<MovieDbModel> response);
#GET("/3/discover/movie?sort_by=vote_average_desc&api_key=xxxxxxxx")
void getMoviesByVotingDesc(Callback<MovieDbModel> response);
}
UPDATED DATA CALL THAT WORKS:
private void makeDataCall(String sortPreference) {
final RestAdapter restadapter = new RestAdapter.Builder().setEndpoint(ENDPOINT_URL).build();
MovieDatabaseApiCient apiLocation = restadapter.create(MovieDatabaseApiCient.class);
if (sortPreference.equals(this.getString(R.string.sort_order_popularity)) ){
apiLocation.getMoviesByPopularityDesc (new Callback<MovieDbModel>() {
#Override
public void success(MovieDbModel movieModels, Response response) {
movieDbResultsList = movieModels.getResults();
MoviesGridViewAdapter adapter = new MoviesGridViewAdapter(getApplicationContext(), R.layout.movie_gridview_item, movieDbResultsList);
gridView.setAdapter(adapter);
}
#Override
public void failure(RetrofitError error) {
Log.d("ERROR", error.toString());
Toast.makeText(getApplicationContext(), "Error: " + error.toString(), Toast.LENGTH_SHORT).show();
}
});
} else {
apiLocation.getMoviesByVotingDesc( new Callback<MovieDbModel>() {
#Override
public void success(MovieDbModel movieModels, Response response) {
movieDbResultsList = movieModels.getResults();
MoviesGridViewAdapter adapter = new MoviesGridViewAdapter(getApplicationContext(), R.layout.movie_gridview_item, movieDbResultsList);
gridView.setAdapter(adapter);
}
#Override
public void failure(RetrofitError error) {
Log.d("ERROR", error.toString());
Toast.makeText(getApplicationContext(), "Error: " + error.toString(), Toast.LENGTH_SHORT).show();
}
});
}
}
My call for the data:
private void makeDataCall (String apiKey, String sortPreference) {
final RestAdapter restadapter = new RestAdapter.Builder().setEndpoint(ENDPOINT_URL).build();
MovieDatabaseApiCient apiLocation = restadapter.create(MovieDatabaseApiCient.class);
apiLocation.getData(apiKey, sortPreference, new Callback<MovieDbModel>){
#Override
public void success(MovieDbModel movieModels, Response response) {
movieDbResultsList = movieModels.getResults();
MoviesGridViewAdapter adapter = new MoviesGridViewAdapter(getApplicationContext(), R.layout.movie_gridview_item, movieDbResultsList);
gridView.setAdapter(adapter);
}
#Override
public void failure(RetrofitError error) {
Log.d("ERROR", error.toString());
Toast.makeText(getApplicationContext(), "Error: " + error.toString(), Toast.LENGTH_SHORT).show();
}
});
}
I found a way to do Synchronously, but not asynchronously.
From your question and comment, IHMO, you should import retrofit.Callback; instead of import com.squareup.okhttp.Callback;
My code as the following has no compile error:
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// creating a RestAdapter using the custom client
RestAdapter restAdapter = new RestAdapter.Builder()
.setEndpoint(API_URL_BASE)
.setLogLevel(RestAdapter.LogLevel.FULL)
.setClient(new OkClient(mOkHttpClient))
.build();
WebService webService = restAdapter.create(WebService.class);
retrofit.Callback<GetRoleData> callback = new Callback<GetRoleData>() {
#Override
public void success(GetRoleData getRoleData, retrofit.client.Response response) {
}
#Override
public void failure(RetrofitError error) {
}
};
webService.getData("api_key", "sort_by", callback);
}
Interface:
public interface WebService {
#GET("/3/discover/movie")
void getData(#Query("api_key") String apiKey, #Query("sort_by") String sortByValue, Callback<GetRoleData> response);
}
So, please check your code again

Retrofit Observables and access to Response

I'm using Retrofit and RxJava but can't seem to do what I want.
Here's my declaration of my web service:
Observable<Response> rawRemoteDownload(#Header("Cookie") String token, #Path("programId") int programId);
The problem I have is the webservice is returning a 403 and a json payload with details.
Retrofit calls onError, only passing the Throwable so I can't check the response body.
Here's part of my test code
apiManager.rawRemoteDownloadRequest("token", 1).subscribe(new Observer<Response>() {
#Override
public void onCompleted() {
}
#Override
public void onError(Throwable e) {
// this is called and I've lost the response!
}
#Override
public void onNext(Response response) {
}
});
SOLUTION:
Thanks to Gomino, I went with this as a solution:
new Action1<Throwable>() {
#Override
public void call(Throwable throwable) {
if (throwable instanceof RetrofitError) {
Response response = ((RetrofitError) throwable).getResponse();
System.out.println(convertToString(response.getBody()));
}
}
where convertToString looks like:
private String convertToString(TypedInput body) {
byte[] bodyBytes = ((TypedByteArray) body).getBytes();
return new String(bodyBytes);
}
Check if the throwable is a RetrofitError:
#Override
public void onError(Throwable e) {
if (e instanceof RetrofitError) {
Response response = ((RetrofitError) e).getResponse();
}
}

#Context WebConfig not injected when using JerseyTest 2.0

I have a simple resource like:
#Path("/")
public class RootResource {
#Context WebConfig wc;
#PostConstruct
public void init() {
assertNotNull(wc);
}
#GET
public void String method() {
return "Hello\n";
}
}
Which I am trying to use with JerseyTest (2.x, not 1.x) and the GrizzlyTestContainerFactory.
I can't work out what I need to do in terms of config to get the WebConfig object injected.
I solved this issue by creating a subclass of GrizzlyTestContainerFactory and explicitly loading the Jersey servlet. This triggers the injection of the WebConfig object. The code looks like this:
public class ExtendedGrizzlyTestContainerFactory implements TestContainerFactory {
private static class GrizzlyTestContainer implements TestContainer {
private final URI uri;
private final ApplicationHandler appHandler;
private HttpServer server;
private static final Logger LOGGER = Logger.getLogger(GrizzlyTestContainer.class.getName());
private GrizzlyTestContainer(URI uri, ApplicationHandler appHandler) {
this.appHandler = appHandler;
this.uri = uri;
}
#Override
public ClientConfig getClientConfig() {
return null;
}
#Override
public URI getBaseUri() {
return uri;
}
#Override
public void start() {
if (LOGGER.isLoggable(Level.INFO)) {
LOGGER.log(Level.INFO, "Starting GrizzlyTestContainer...");
}
try {
this.server = GrizzlyHttpServerFactory.createHttpServer(uri, appHandler);
// Initialize and register Jersey Servlet
WebappContext context = new WebappContext("WebappContext", "");
ServletRegistration registration = context.addServlet("ServletContainer", ServletContainer.class);
registration.setInitParameter("javax.ws.rs.Application",
appHandler.getConfiguration().getApplication().getClass().getName());
// Add an init parameter - this could be loaded from a parameter in the constructor
registration.setInitParameter("myparam", "myvalue");
registration.addMapping("/*");
context.deploy(server);
} catch (ProcessingException e) {
throw new TestContainerException(e);
}
}
#Override
public void stop() {
if (LOGGER.isLoggable(Level.INFO)) {
LOGGER.log(Level.INFO, "Stopping GrizzlyTestContainer...");
}
this.server.stop();
}
}
#Override
public TestContainer create(URI baseUri, ApplicationHandler application) throws IllegalArgumentException {
return new GrizzlyTestContainer(baseUri, application);
}
Notice that the Jersey Servlet configuration is being loaded from the ApplicationHandler that is passed in as a parameter using the inner Application object's class name (ResourceConfig is a subclass of Application). Therefore, you also need to create a subclass of ResourceConfig for this approach to work. The code for this is very simple:
package com.example;
import org.glassfish.jersey.server.ResourceConfig;
public class MyResourceConfig extends ResourceConfig {
public MyResourceConfig() {
super(MyResource.class);
}
}
This assumes the resource you are testing is MyResource. You also need to override a couple of methods in your test like this:
public class MyResourceTest extends JerseyTest {
public MyResourceTest() throws TestContainerException {
}
#Override
protected Application configure() {
return new MyResourceConfig();
}
#Override
protected TestContainerFactory getTestContainerFactory() throws TestContainerException {
return new ExtendedGrizzlyTestContainerFactory();
}
#Test
public void testCreateSimpleBean() {
final String beanList = target("test").request().get(String.class);
Assert.assertNotNull(beanList);
}
}
Finally, for completeness, here is the code for MyResource:
#Path("test")
public class MyResource {
#Context WebConfig wc;
#PostConstruct
public void init() {
System.out.println("WebConfig: " + wc);
String url = wc.getInitParameter("myparam");
System.out.println("myparam = "+url);
}
#GET
#Produces(MediaType.APPLICATION_JSON)
public Collection<TestBean> createSimpleBean() {
Collection<TestBean> res = new ArrayList<TestBean>();
res.add(new TestBean("a", 1, 1L));
res.add(new TestBean("b", 2, 2L));
return res;
}
#POST
#Produces(MediaType.APPLICATION_JSON)
#Consumes(MediaType.APPLICATION_JSON)
public TestBean roundTrip(TestBean s) {
return s;
}
}
The output of running the test shows that the WebConfig is loaded and the init param is now available:
WebConfig: org.glassfish.jersey.servlet.WebServletConfig#107d0f44
myparam = myvalue
The solution from #ametke worked well but wasn't picking up my ExceptionMapper classes. To solve this I simplified the start() method to:
#Override
public void start() {
try {
initParams.put("jersey.config.server.provider.packages", "my.resources;my.config");
this.server = GrizzlyWebContainerFactory.create(uri, initParams);
} catch (ProcessingException | IOException e) {
throw new TestContainerException(e);
}
}
This was based on Problems running JerseyTest when dealing with HttpServletResponse

Spring MVC Jsonp filter incorrect response. (Content length cuts of response output)

I'm trying to implement this Jsonp Filter.
However, whenever I call my url /server/api.jsonp?callback=something it cuts of the last part of the response (ContentLength has the length of the original response output. In this case that would be 15 since {test: 'blaat'} is my original response output - see Controller).atleast this is what I assume since the output I get is test({test: 'bl. Does someone know how to get the filter to work and send the correct response back?
(I even try to force the Content-length - see JsonpCallbackFilter)
Filter:
public class JsonpCallbackFilter implements Filter {
protected final Log logger = LogFactory.getLog(JsonpCallbackFilter.class);
#Override
public void init(FilterConfig fConfig) throws ServletException {
}
#Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
HttpServletRequest httpRequest = (HttpServletRequest) request;
HttpServletResponse httpResponse = (HttpServletResponse) response;
Map<String, String[]> params = httpRequest.getParameterMap();
if (params.containsKey("callback")) {
if (logger.isDebugEnabled()) {
logger.debug("Wrapping response with JSONP callback: " + params.get("callback")[0]);
}
OutputStream out = httpResponse.getOutputStream();
GenericResponseWrapper wrapper = new GenericResponseWrapper(httpResponse);
chain.doFilter(request, wrapper);
byte[] callBack = (params.get("callback")[0] + "(").getBytes();
byte[] callBackEnd = (");").getBytes();
byte[] jsonpResponse = new byte[callBack.length + wrapper.getData().length + callBackEnd.length];
System.arraycopy(callBack, 0, jsonpResponse, 0, callBack.length);
System.arraycopy(wrapper.getData(), 0, jsonpResponse, callBack.length, wrapper.getData().length);
System.arraycopy(callBackEnd, 0, jsonpResponse, callBack.length + wrapper.getData().length, callBackEnd.length);
logger.debug(new String(jsonpResponse));
logger.debug("Length: " + jsonpResponse.length);
out.write(jsonpResponse);
wrapper.setContentType("text/javascript;charset=UTF-8");
wrapper.setContentLength(jsonpResponse.length);
} else {
if (logger.isDebugEnabled()) {
logger.debug("No callback found, resort to default json request!");
}
chain.doFilter(request, response);
}
}
#Override
public void destroy() {
}
}
Generic Response Wrapper:
public class GenericResponseWrapper extends HttpServletResponseWrapper {
private ByteArrayOutputStream output;
private FilterServletOutputStream filterStream;
private PrintWriter printWriter;
private int contentLength;
private String contentType;
public GenericResponseWrapper(HttpServletResponse response) {
super(response);
output = new ByteArrayOutputStream();
filterStream = new FilterServletOutputStream(output);
printWriter = new PrintWriter(output, true);
}
public byte[] getData() {
printWriter.close();
return output.toByteArray();
}
#Override
public ServletOutputStream getOutputStream() {
return filterStream;
}
#Override
public PrintWriter getWriter() {
return printWriter;
}
public int getContentLength() {
return contentLength;
}
#Override
public void setContentLength(int length) {
this.contentLength = length;
super.setContentLength(length);
}
#Override
public String getContentType() {
return contentType;
}
#Override
public void setContentType(String contentType) {
this.contentType = contentType;
super.setContentType(contentType);
}
}
Custom Filter outputstream:
public class FilterServletOutputStream extends ServletOutputStream {
private DataOutputStream stream;
public FilterServletOutputStream(OutputStream output) {
stream = new DataOutputStream(output);
}
#Override
public void write(int b) throws IOException {
stream.write(b);
}
#Override
public void write(byte[] b) throws IOException {
stream.write(b);
}
#Override
public void write(byte[] b, int off, int len) throws IOException {
stream.write(b, off, len);
}
}
web.xml filter mapping:
<filter>
<filter-name>jsonpCallbackFilter</filter-name>
<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
</filter>
<filter-mapping>
<filter-name>jsonpCallbackFilter</filter-name>
<url-pattern>*.jsonp</url-pattern>
</filter-mapping>
bean mapping in applicationContext.xml
<bean id="jsonpCallbackFilter" class="com.world2.utils.spring.filters.jsonp.JsonpCallbackFilter" />
Controller:
#Controller
public class ApiRequests {
protected final Logger logger = Logger.getLogger(ApiRequests.class);
#RequestMapping(value = "api.json", produces = {"application/json"}, method = RequestMethod.GET)
#ResponseBody
public String handleActionJson(final HttpServletRequest request){
return "{test: 'blaat'}";
}
#RequestMapping(value = "api.jsonp", produces = {"text/javascript", "application/javascript", "application/json"}, method = RequestMethod.GET)
#ResponseBody
public String handleActionJsonp(final HttpServletRequest request){
return "{test: 'blaat'}";
}
}
Url I try to call:
http://host:8084/MyProject/server/api.jsonp?callback=test&_=1364980436087
Debug output:
11:13:57,776 DEBUG JsonpCallbackFilter:57 - test({test: 'blaat'});
11:13:57,776 DEBUG JsonpCallbackFilter:58 - Length: 22
Result:
test({test: 'bl
instead of expected result:
test({test: 'blaat'});
Apparently I had to first set the content length and then write the ouput.
Right:
wrapper.setContentType("text/javascript;charset=UTF-8");
wrapper.setContentLength(jsonpResponse.length);
out.write(jsonpResponse);
Wrong:
out.write(jsonpResponse);
wrapper.setContentType("text/javascript;charset=UTF-8");
wrapper.setContentLength(jsonpResponse.length);

Resources