I need to get the response Java object that is returned from my service for some processing of the data. I don't want to write the code to process this data in the ServiceImpl class itself since I want to keep it configuration based. I have written the out interceptor.
As per answer to this question , the POJO object should be available in the out interceptor, however I see that the object is actually an intermediate class of response. I get a ClassCastException with the code mentioned in above link.
Am I missing something? Can the same POJO object returned by Service class be available in the Out interceptor?
Any other approach to accomplish this is also welcome.
MyOutInterceptor.java:
public class MyOutInterceptor extends AbstractPhaseInterceptor<Message> {
public MyOutInterceptor() {
super(Phase.MARSHAL); // Tried Phase.PRE_LOGICAL as well
}
public void handleMessage(Message message) throws Fault {
MessageContentsList objs = MessageContentsList.getContentsList(message);
if (objs != null && objs.size() == 1) {
Object responseObj = objs.get(0);
MyData data = (MyData) responseObj; // fails here with ClassCastException
...
}
applicationContext.xml
<bean class="com.xyz.interceptor.MyOutInterceptor" id="outInterceptor" />
<jaxws:endpoint id="dataService" implementor="#masterDataService" address="/MasterDataService">
...
<jaxws:outInterceptors>
<ref bean="outInterceptor" />
</jaxws:outInterceptors>
</jaxws:endpoint>
Pre-logical phase will work, but you would need to do an:
addBefore(WrapperClassOutInterceptor.class.getName());
to make sure it's run before that interceptor.
Related
I am new for spring security. I've seen many posts on how to inject values via annotation from external property file. I've tried many ways, but I always end up with java.lang.IllegalArgumentException: Could not resolve placeholder 'val.id' exception.
Can you provide me some tips how to handle this exception please?
My java class is the following one:
#Controller
public class Employee {
#Value("${val.id}")
public String valId;
public String getValId() {
return valId;
}
public void setValId(String valId) {
this.valId = valId;
}
My property file is called val.properties which is located under WEB-INF, and its content is
val.id=xyz
I put the following in my main context bean.
<context:property-placeholder location="/WEB-INF/*.properties" />
<bean id="valProp" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"
p:location="/WEB-INF/val.properties"/>
A continuous question:
The injecting values from properties file to annotated beans works fine as I accepted the answer above. However, I cannot able to inject it to #PreAuthorize(...) annotation by following the same procedure.
Assume I want to secure a method called 'update'. This method is allowed if and only if valId is equal to empId. values of valId and empId are initialized in the val.properties file.
my java bean is:
public class Employee {
public String valId;
public String empId;
public String getValId() {
return valId;
}
public void setValId(String valId) {
this.valId = valId;
}
public String getEmpId() {
return empId;
}
public void setEmpId(String empId) {
this.empId = empId;
}
}
my property file contains:
val.id=nn
emp.id=nn
I have the place holder configuration in my main context file:
<context:property-placeholder location="/WEB-INF/*.properties" />
<bean id="valProp" class="org.springframework.beans.factory.config.PropertiesFactoryBean"
p:location="/WEB-INF/val.properties"/>
My PreAuthorize annotation (method security) is:
#PreAuthorize("(#{valProp['val.id']} == #{valProp['emp.id']})")
public boolean update(){
//if accessable
return true;
}
But the expression #{valProp['val.id']} == #{valProp['emp.id']} is not evaluated.
Did I do any mistake to inject values? It was worked when I annotate member variables, but it doesn't work here. Any idea please? Thanks in advance.
try to consider the following
1). change your annotation to:
#Value("#{valProp['val.id']}")
2). Replace PropertyPlaceholderConfigurer by PropertiesFactoryBean.
Hope this will resolve the exception.
The reason why the exception is thrown is, because the property placeholder by default throws an exception when a values cannot be resolved.
Furthermore you have two property placeholders, via which probably not all values can be resolved.
You can change this behaviour via setting the ignore-unresolvable property:
<context:property-placeholder location="/WEB-INF/*.properties" ignore-unresolvable="true" />
<bean id="valProp" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"
p:location="/WEB-INF/val.properties" p:ignoreUnresolvablePlaceholders="true" />
Note however that b< turning off this feature typos in a property file will not be detected.
I'm using Spring 3.1.1.RELEASE and JUnit 4.11. I setup my JUnit tests like so
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration({ "classpath:test-context.xml" })
public class MySpringTest
{
protected MockHttpServletRequest request;
protected MockHttpServletResponse response;
protected MockHttpSession session;
#Autowired
protected RequestMappingHandlerAdapter handlerAdapter;
#Autowired
protected RequestMappingHandlerMapping handlerMapping;
When testing controllers, I have this line to verify that the view the controller's method is returning is the right view …
import static org.springframework.test.web.ModelAndViewAssert.assertViewName;
...
final ModelAndView mav = submitMyForm(…);
assertViewName(mav, "folder/myView");
...
protected ModelAndView submitMyForm(… params ...) throws Exception {
request = new MockHttpServletRequest();
response = new MockHttpServletResponse();
request.setRequestURI("/myurl");
request.setMethod("POST");
request.addParameter("param1", param1);
...
final Object handler = handlerMapping.getHandler(request).getHandler();
return handlerAdapter.handle(request, response, handler);
}
My question is, once I verify the view returned my the controller is the expected view, how do I verify it won't result in a 404? The main problem I'm gaving now is testing whether or not the view actually maps to an underlying page in my WAR file.
why don't use spring-mvc-test and do something like this ?
#Autowired
private ViewResolver viewResolver;
// code
View view = viewResolver.resolveViewName(viewName, locale);
//assert view not null
or something like this, in wich you can check both if the view is ok and the returned status (is status 200/404?)
(more code here: http://goo.gl/fMqBsl)
#Test
public void indexTest() throws Exception {
mockMvc.perform(get("/")).andDo(print())
.andExpect(handler().handlerType(MainController.class))
.andExpect(handler().methodName("index"))
.andExpect(view().name("index"))
.andExpect(forwardedUrl("/WEB-INF/tiles/template.jsp"))
.andExpect(status().isOk());
}
i am using standard jsp view
basically, you need to know the view resolver(s). can a specific view be resolved? that means, if you DON'T have a file called abc.xml, it might still be a valid view.
for simplicity sake, lets assume that we have only one view resolver, and, its
"org.springframework.web.servlet.view.UrlBasedViewResolver"
and here is the bean definition
spring 3.2.4 documentation pdf, page 477
<bean id="viewResolver"
class="org.springframework.web.servlet.view.UrlBasedViewResolver">
<property name="viewClass" value="org.springframework.web.servlet.view.JstlView"/>
<property name="prefix" value="/WEB-INF/jsp/"/>
<property name="suffix" value=".jsp"/>
</bean>
eg: the view name "page1" => /WEB-INF/jsp/page1.jsp and "admin/page2" => /WEB-INF/jsp/admin/page2.jsp
using this, you can Inject the view resolved to your junit test using #Autowired and/or #Qualifier
then read the "prefix" and suffix value and find the full path like "src/main/webapp/" + prefix + viewname + suffix
and check if the file exists.
you may have multiple view resolvers, so you may want to inject the context and handle the view => filename resolution using a strategy pattern.
something like
foreach resolver
{
if i can resolve the view to a file (resolver type, viewname)
return the physical filename
else
try next resolver
}
I've seen that you can control cache http headers with the AnnotationMethodHandlerAdapter bean.
My problem is that I need to have a fine grane control on the cache (at method level).
The best think would be to have something like an annotation like "#RequestCache(expire=60)".
Is there anything like this?
What is the best way to accomplish this task?
Thanks,
Andrea
Update:
pap suggest to use an HandlerInterceptor, but I've seen multiple forum's post saying that it's not possible to get the target method inside an HandlerInterceptor and suggest to use regular AOP instead (not specifically for caching).
The problem is that I don't want to add the request parameter to all my methods, only to make it accessible to the aspect. Is there a way to avoid this?
You can use the following approach described in
Spring mvc reference manual
Support for the 'Last-Modified' Response Header To Facilitate Content Caching
#RequestMapping(value = "/modified")
#ResponseBody
public String getLastModified(WebRequest request) {
if (request.checkNotModified(lastModified.getTime())) {
logger.error("Was not modified.");
return null;
}
logger.error("Was modified.");
//processing
return "viewName";
}
One way (that I have used myself) is to create your own HandlerInterceptor.
public class CacheInterceptor implements HandlerInterceptor {
#Override
public boolean preHandle(HttpServletRequest request,
HttpServletResponse response, Object handler) throws Exception {
Class<?> o = AopUtils.getTargetClass(handler);
if (o.isAnnotationPresent(RequestCache.class)) {
response.setDateHeader("Expires", o.getAnnotation(RequestCache.class).expire());
}
return true;
}
...
}
and then
<bean class="org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping">
<property name="interceptors">
<array>
<bean class="bla.bla.CacheInterceptor " />
</array>
</property>
</bean>
i read the documentation here:
http://static.springsource.org/spring/docs/2.0.x/api/org/springframework/web/servlet/view/BeanNameViewResolver.html
but i think that the spring documentation sometimes can become complex and hard to understand, so i need little explanation about this class.
As described in the documentation, BeanNameViewResolver resolves Views declared as beans. Usually you need it for some special-purpose views.
Imagine, for example, that one of your controllers should render an Excel spreadsheet. So, you subclass AbstractExcelView and implement your custom logic to render a spreadsheet based on model values:
public class MyExcelView extends AbstractExcelView { ... }
and declare it as a bean:
<bean id = "myExcelView" class = "MyExcelView" />
Then declaring an BeanNameViewResolver makes it available to controllers: when controller returns ModelAndView with view name myExcelView, your spreadsheet will be rendered.
BeanNameViewResolver is usually used in conjunction with some other view resolver that handles "regular" views (so that if BeanNameViewResolver can't find a view, the other resolver tries to find it):
<bean class = "...BeanNameViewResolver">
<property name = "order" value = "0" />
</bean>
<bean class = "...InternalResourceViewResolver">
<property name = "order" value = "1" />
...
</bean>
Indeed the documentation is not fantastic.
The view resolver in spring mvc is a bean which translates from view names to views.
A view name is s simple string. It is returned by the controller's handleRequest() method within the ModelAndView object.
ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) {
....
return ModelAndView("thisIsTheViewName", ...);
}
This view name is resolved to an actual view class by the view resolver.
The BeanNameViewResolver has an easy job: It looks for a view bean in the applicationContext which has this view name as its id.
<bean id="thisIsTheViewName" class="....MyView" />
For simple applications this can be the simplest way to translate from view name to view.
If you are looking for a very simple but complete example:
#Controller
public class MyController {
#GetMapping("/hello")
public String getHello() {
return "helloView";
}
}
#Component
public class HelloView extends AbstractView {
#Override
protected void renderMergedOutputModel(Map<String, Object> map,
HttpServletRequest req, HttpServletResponse res) throws Exception {
res.setContentType("text/plain");
res.getOutputStream().println("hello world");
}
}
supose I have the following example:
#Transactional(propagation=Propagation.SUPPORTS, readOnly=true)
public class MyServiceImpl implements MyService {
...
#Transactional(propagation=Propagation.REQUIRED, readOnly=false)
public TransactionResponse addMyEntity(MyEntity e) throws SQLException{
...
}
...
}
And in my applicationContext:
<tx:annotation-driven transaction-manager="txManager" />
Ok, now I want to add an interceptor after the rollback of the transaction if an SQLException is thrown. How can I do this?
Thanks in advance
EDIT
I'll try to clarify what I'm trying to do:
I have a WS, that persists some information on a DB and returns a response (an isOk boolean and an errorMessage if something went wrong)
Whenever an exception is risen, I need to:
Rollback the transaction
Build the response with the error message and return it to the client.
It's like a try/catch around spring's transaction proxy
Use the order attribute of tx:annotation-driven, and of the interceptor you will be using. Thus you specify which one runs before the other. See the AOP AspectJ advice ordering section