Spring 5.3.9 - AbstractPDF controller - spring

I am upgrading the very old Spring framework to 5.3.9. All my controllers are working with annotations. Having issue (Error 404: SRVE0295E: Error reported: 404) when calling exiting PDF generator controller. Below is the flow of the call. Could someone help me what am I missing ? Thank you!
//From the controller
If(action = "PRINT")
return new ModelAndView("individualApplication.pdf.html","model",model);
}
//PDF controller
public class IndividualApplicationPdfPublicController extends AbstractPdfView {
public void buildPdfDocument(Map model, Document document,
PdfWriter pdfWriter, HttpServletRequest request,
HttpServletResponse response) throws Exception {}
}
//Configuration
<beans:bean id="individualApplication.pdf.html" class="controller.pdf.IndividualApplicationPdfPublicController">
</beans:bean>
<beans:bean id="publicUrlMapping" class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
<beans:property name="mappings">
<beans:props>
<beans:prop key="/public/individualApplication.pdf.html">individualApplication.pdf.html</beans:prop>
</beans:props>
</beans:property>
</beans:bean>

I have solved the issue.
Updated the PDF controller removing the AbstarctPdfView extension.
pdfWriter = PdfWriter.getInstance(document, outputStream);
Updated the controller to get the byteArray to flush to the browser.
Return to the same page to stay on the same page.

Related

Spring Integration: ClientHttpRequestInterceptor intercept() method not called when request is sent

I have set up a spring-integration application as followed, and want to log the outbound request using ClientHttpRequestInterceptor.
The setup is below.
I sent the Http-get using curl and got result, but the method CustomClientHttpRequestInterceptor.intercept() never gets called when app is debugged.
I must have missed something in the setup. Thanks for helping.
Configuration:
<bean id="customRT" class="org.springframework.web.client.RestTemplate">
<property name="interceptors">
<list>
<bean class="hello.CustomClientHttpRequestInterceptor" />
</list>
</property>
</bean>
<int:chain...>
<int:header-enricher....
<int-http:outbound-gateway url="http://example.com/vhosts"
rest-template="customRT"
http-method="GET"/>
</int:chain>
public class CustomClientHttpRequestInterceptor implements ClientHttpRequestInterceptor {
Logger logger = LoggerFactory.getLogger(this.getClass());
#Override
public ClientHttpResponse intercept(HttpRequest request, byte[] body, ClientHttpRequestExecution execution)
throws IOException {
logger.info("request.getURI().toString());
return execution.execute( request, body );
}
The configuration and code are correct. I've forgot that there is a cache installed, and that's why the intercept() method never gets called.

With Spring MVC can you make one controller call another controller to handle an error page?

I have a controller which can throw an exception. When it does throw an exception it will show my errorpage.jsp, instead of the jsp page I wanted to show. An exxample of this controller is:
public class myController implements Controller {
public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) throws Exception {
Map<String, Object> model = new HashMap<>();
// Some logic which can throw an error....
return model;
}
}
The application-servlet.xml looks like this:
...
<bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="viewClass" value="org.springframework.web.servlet.view.JstlView"/>
<property name="prefix" value="/WEB-INF/"/>
<property name="suffix" value=".jsp"/>
</bean>
<bean id="urlMapping" class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
<property name="mappings">
<props>
<prop key="/login.html">myController</prop>
<prop key="/errorpage.html">myErrorController</prop>
</props>
</property>
</bean>
...
Normally when an error, like navigating to a page that doesn't exist, occurs the error controller will be called which will return a hashmap of variables for the error page jsp. However, when the login controller encounters an error it will show the error page, but it won't call the error controller which would provide some of these parameters, so the page is incomplete.
Is there some way to define in the servlet.xml for the myController to call the myErrorController when it encounters an error and redirects to the error page?
You can annotate a controller class with #ControllerAdvice which will be shared between all Controllers. Then using the #ExceptionHandler annotation you can create methods to handle specific exceptions.
Example:
#ControllerAdvice
public class ExceptionHandlerAdvice {
#ExceptionHandler(MyException.class)
public ModelAndView handleException(MyException e, HttpServletRequest request, HttpServletResponse response) { // included servlet request and response
ModelAndView model = new ModelAndView("error/errorpage.jsp");
model.addObject("exception", e);
return model;
}
}
And anytime you throw MyException in any of your other controllers, this controller advice method will handle the exception for you! As the exception, servlet request and response is passed to the ExceptionHandler method, all of that information is available to you.
Example in another controller:
#Controller
public class SomeController {
#Autowired
private DataService dataService;
#RequestMapping(value = '/', method = RequestMethod.POST)
public String doSomething() {
return dataService.foobar(); // throws MyException which is handled with ExceptionHandler
}
}

Spring 2.5 Ajax 1.7, updater receive wrong response

I am using Spring 2.5, and use Ajax.updater (1.7) to get an response from an requestmapping in Spring.
In the request mapping I am returning an ModelAndView which refers to an jsp with some text. But the problem is that when ajax received the response and update the container, the entire page is wrapped in the container instead just the jsp output, why is this
Ok, this is how I used ajax with Spring 2.5
First of all you need controller to respond on ajax calls
public class AjaxController extends MultiActionController {
// injected services, daos here
public ModelAndView getAjaxData(HttpServletRequest request, HttpServletResponse response) throws Exception {
String data = // construct your ajax response here - string, json, xml etc
model.put("data", data);
return new ModelAndView("ajax_foo", model);
}
public ModelAndView anotherMethod(HttpServletRequest request, HttpServletResponse response) throws Exception {
String data = // construct your ajax response here - string, json, xml etc
model.put("data", data);
return new ModelAndView("ajax_foo", model);
}
}
Then you need ajaxView to write ajax data to response
public class AjaxView extends AbstractView {
#Override
protected void renderMergedOutputModel(Map map, HttpServletRequest request, HttpServletResponse response) throws Exception {
String ajaxResponse = map.get("data");
response.setContentType("text/plain; charset=UTF-8");
response.getOutputStream().write(ajaxResponse.getBytes());
}
View resolver to resolve ajax calls
public class AjaxViewResolver extends AbstractCachingViewResolver {
private String ajaxPrefix;
private View ajaxView;
#Override
protected View loadView(String viewName, Locale locale) throws Exception {
View view = null;
if (viewName.startsWith(this.ajaxPrefix)) {
view = ajaxView;
} else {
}
return view;
}
public void setAjaxPrefix(String ajaxPrefix) {
this.ajaxPrefix = ajaxPrefix;
}
public void setAjaxView(View ajaxView) {
this.ajaxView = ajaxView;
}
}
Url mapping, map ajax url to ajax controller
<bean id="simpleUrlMapping" class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
<property name="mappings">
<props>
<prop key="/getAjaxData.htm">ajaxController</prop>
<prop key="/anotherMethod.htm">ajaxController</prop>
</props>
</property>
</bean>
Controller has bean ajaxResolver as methodNameResolver, controller has some services or daos for example
<bean name="ajaxController" class="my.test.web.ajax.AjaxController">
<property name="service" ref="service"/>
<property name="dao" ref="dao"/>
<property name="methodNameResolver" ref="ajaxResolver"/>
</bean>
Method name resolver
<bean id="ajaxResolver"
class="org.springframework.web.servlet.mvc.multiaction.PropertiesMethodNameResolver">
<property name="mappings">
<props>
<prop key="/getAjaxData.htm">getAjaxData</prop>
<prop key="/anotherMethod.htm">anotherMethod</prop>
</props>
</property>
</bean>
Ajax View resolver to call your ajax view when you return modelAndView from AjaxController
<bean id="ajaxViewResolver" class="my.test.web.ajax.AjaxViewResolver">
<property name="ajaxView">
<bean class="my.test.web.ajax.AjaxView"/>
</property>
<property name="ajaxPrefix" value="ajax_"/>
</bean>

Spring dependency injection to other instance

from the app-context.xml:
<bean id="userDao" class="com.vaannila.dao.UserDAOImpl">
<property name="sessionFactory" ref="mySessionFactory"/>
</bean>
<bean name="MyServiceT" class="com.s.server.ServiceT">
<property name="userDao" ref="userDao"/>
</bean>
and inside ServiceT.java:
private UserDAO userDao;
public void setUserDao(UserDAO userDao){
this.userDao = userDao;
}
the issue is: the setUserDao is called when the server goes on but when I call my doGet method:
protected void doGet(HttpServletRequest request,
HttpServletResponse response) throws ServletException, IOException {
PrintWriter writer = response.getWriter();
writer.write("hello");
}
the userDao is null.
I put a breakpoint inside the setUserDao method and than another one inside the doGet method and saw that it is not the same insatnce... what is the reason? how can I fix it?
thanks!
Spring is atowiring your bean correctly, the problem is that servlet container instantiates your servlet independently of spring. So you basically have two different instances - one created by spring and another created by container.
One workaround is to use ServletContextAttributeExporter, by putting the following in your app-context.xml:
<bean class="org.springframework.web.context.support.ServletContextAttributeExporter">
<property name="attributes">
<map>
<entry key="userDao">
<ref bean="userDao"/>
</entry>
</map>
</property>
and then, in your servlet:
protected void doGet(HttpServletRequest request,
HttpServletResponse response) throws ServletException, IOException {
UserDao userDao = (UserDao)getServletContext().getAttribute("userDao");
// do something with userDao
PrintWriter writer = response.getWriter();
writer.write("hello");
}
another is to access the WebApplicationContext directly:
protected void doGet(HttpServletRequest reqest, HttpServletResponse response)
throws ServletException, IOException {
WebApplicationContext springContext = WebApplicationContextUtils.getWebApplicationContext(getServletContext());
UserDao userDao =(UserDao)springContext.getBean("userDao");
}
... or simply use Spring MVC and let it autowire everything like it should.
Also see this blog post. It might be easier to convert your servlet to HttpRequestHandler and let it be served by HttpRequestHandlerServlet, both provided by spring.

Spring : Command object not getting populated

I have two controllers , a simple form controller and a multiaction controller.
Now, in simpleformcontroller, i want to redirect a request to multiaction controller.
Here's code snippet in simpleformcontroller
protected ModelAndView onSubmit(HttpServletRequest request, HttpServletResponse response, Object command, BindException errors) {
MyObject myOb = (MyObject )command;
system.out.println(myOb.toString);
ModelAndView mav = new ModelAndView(new RedirectView("another.htm"));
mav.addObject("Obj",myOb);
return mav;
}
another.htm binds to a method in multiaction controller.
<bean id="MyController" class="MyController">
<property name="methodNameResolver">
<bean class="org.springframework.web.servlet.mvc.multiaction.PropertiesMethodNameResolver">
<property name="mappings">
<props>
<prop key="/another.htm">another</prop>
</props>
</property>
</bean>
</bean>
and the code in multiactioncontroller is
public class MyController extends MultiActionController {
public ModelAndView another(HttpServletRequest request,
HttpServletResponse response, MyObject myObj) {
system.out.println(myObj.toString());
}
}
The output is, all fields of Myobj are nulls in mutiactioncontroller whereas they have valid values when passed in simpleformcontroller.
Am i missing something here or is this not the right way to pass command objects ?
Any help is appreciated.
Unless you store your MyObject in The session, you will always get null. It occurs because The user data does not survive redirect. To store your command object in The session, use setSessionForm in The SimpleFormController and Then retrieve your command by using
public ModelAndView another(HttpServletRequest request, HttpServletResponse response, HttpSession session, MyObject myObj) throws CRPMException {
instead

Resources