Spring - Specify Implementation class of Model within Controller methods - spring

For the most part I'm trying to code to interfaces as much as possible. But I'm having problems with a Spring Controller method signature. If I actually write the signature using the Model's interface, I end up getting the following exception:
BeanInstantiationException: Could not instantiate bean class[PageModel]: Specified class is an interface
Granted, I know that it's an interface, and if I change it to the actual implementation class, it works just fine. But is there no way to code to the interface? An annotation or something to tell Spring which bean to instantiate? btw, I'm using annotation configuration.
#RequestMapping("SpecificPageController")
public interface PageController {
#RequestMapping({"", "/load"})
ModelAndView load(#ModelAttribute("model") PageModel model);
}
#Controller
public class SpecificPageController implements PageController {
#Override
public ModelAndView load(final PageModel model) {
}
}
public interface PageModel {
... getters and setters...
}
public class ModelImpl implements PageModel {
... variables, getters, setters...
}

You can use #ModelAttribute on a controller method to get the implementation:
#ModelAttribute
public PageModel getModel() {
return new SpecificPageModel();
}

Related

Spring boot Restcontroller #RoleAllowed in the interface implementation is not working

I have created an interface with a default method that defines the #RequestMapping and #RoleAllowed and implemented in one Restcontroller. But the #RoleAllowed property is not talking from the default method. PFB the code
public interface Resource{
#REquestMapping(value="/api/test",method=RequestMethod.GET)
#RoleAllowed({"READ_ONLY"})
default public String testEndPoint(){
return "defaultmethod";
}
}
public class ResourceImpl implements Resource{
#override
public String testEndPoint(){
return "ResourceImpl";
}
}
}
#RoleAllowed is not working in ResourceImpl. If I am not overriding testEndPoint method it is working fine

Spring Security: get controller class in Preauthorize annotation

Many of the controllers I use in a Spring application extend a common abstract class. The methods are thus declared in the abstract class.
I would like to apply a 'PreAuthorize' condition in the abstract method, but I need to get the name of the actual controller class being invoked to be passed to the EL evaluator.
Is there a way to do so?
In abstract class implement BeanNameAware interface.
public abstract class MyController implements BeanNameAware{
String beanName;
#Override
public void setBeanName(final String beanName) {
this.beanName = beanName;
}
#Override
public String getBeanName() {
return beanName;
}
}
You will get a hold of actual bean name instead regular proxy. If you need further customization implement BeanFactoryAware. You can than use that getBeanName method in SpEl of your preauthorize

Spring Data Rest: custom Converter<Entity, Resource> is never invoked

I'm trying to implement a custom Converter for an Entity to a Resource object with Spring Data Rest, but the Converter is never invoked.
I'm following this documentation:
If your project needs to have output in a different format, however,
it’s possible to completely replace the default outgoing JSON
representation with your own. If you register your own
ConversionService in the ApplicationContext and register your own
Converter, then you can return a Resource
implementation of your choosing.
That's what I've tried to do.
I have a #Configuration class that extends RepositoryRestMvcConfiguration, with this method:
#Configuration
#EnableWebMvc
#EnableHypermediaSupport(type = HypermediaType.HAL)
public class RepositoryBaseConfiguration extends RepositoryRestMvcConfiguration {
#Override
public DefaultFormattingConversionService defaultConversionService() {
return super.defaultConversionService();
}
}
And I have a Class that extends RepositoryRestConfigurerAdapter, with this implementation:
#Configuration
public class RepositoryBaseConfigurerAdapter extends RepositoryRestConfigurerAdapter {
#Override
public void configureConversionService(ConfigurableConversionService conversionService) {
if(!conversionService.canConvert(Entity.class, Resource.class))
conversionService.addConverter(new EntityConverter());
super.configureConversionService(conversionService);
}
}
Both methods of those two classes are correctly invoked and managed, so it's natural to think that the Converter has been registered in the Application Context...
This is my custom converter EntityConverter:
#Component
public class EntityConverter implements Converter<Entity, Resource> {
#Override
public Resource convert(Entity source) {
System.out.println("method convert of class EntityConverter");
return null;
}
}
The method "convert" is never invoked by Spring Data Rest.
What's wrong/missing ?
Thanks in advance.

Dependency injection in Spring MVC?

I am trying to use dependency injection in my Spring MVC web application. I have a function like this in my controller
#RequestMapping(value = "/stockgoogle/", method = RequestMethod.GET)
public #ResponseBody Stock stockGoogle(Locale locale, Model model) {
StockDaoImpl si = new StockDaoImpl();
//al=s.listCurrent(id);
Stock s=si.listGoogle();
System.out.println("reached here");
model.addAttribute("s", s );
return s;
}
I want to dependency inject StockDaoImpl. Can you please tell me how I can do this. I have been trying to read but most of the explainations are very complex. Should I use #Autowired ? Where should I put it? Can you please help.
You can inject it through the Controller's constructor
class YourController{
private final StockDao dao;
#Autowired
public YourController(StockDao dao){
this.dao = dao;
}
}
And now StockDaoImpl has to be defined as a Bean of course,
#Bean
public StockDao stockDao(){
return new StockDaoImpl();
}
Another way for doing it would be defining StockDaoImpl as a Component
Add below config in Spring config file(for example root-context.xml)
then in your controller, you like below code
class TestController{
#Autowired
private StockDao stockDao;
}
With spring-4 you can directly inject in given way :
#Autowired
private StockDao stockDao;
public #ResponseBody Stock stockGoogle(Locale locale, Model model) {
//al=s.listCurrent(id);
Stock s = stockDao.listGoogle();
System.out.println("reached here");
model.addAttribute("s", s );
return s;
}
Here
StockDao will contain method signature
StockDaoImpl implements StockDao and definition of methods
Autowired will inject that Dao and you can use its method.

Using both JSR-303 and Traditional Bean Validation?

Is it possible to use both JSR-303 bean validation and traditional validation (a single validator class for the type) in Spring? If so, what configuration is required to set this up?
I have tried the instructions on the reference.
#InitBinder
protected void initBinder(WebDataBinder binder) {
binder.setValidator(new DualEntryValidator());
}
#RequestMapping(value="/dualEntry.htm", method = RequestMethod.POST)
public ModelAndView handlePost(#Valid DualEntryForm form, BindingResult result) {
ModelAndView modelAndView = new ModelAndView("dualEntry", getCommonModel());
if (!result.hasErrors()){
//do logic
return modelAndView;
}else {
modelAndView.addObject("dualEntryForm", form);
return modelAndView;
}
}
I can get this to use my custom Validator or the JSR-303 validation, but not both. If I have the initBinder present as in the example it uses the custom Validator. If I remove it the JSR-303 bean validation is used. How can I use both?
I've done that following the instructions here:
http://blog.jteam.nl/2009/08/04/bean-validation-integrating-jsr-303-with-spring/
See the "Enjoy both worlds" section. Shortly, you explicitly run a JSR303 validation from a Spring validator, "joining" the results of JSR303 validations based on annotations and your custom validation logic.
I realise this is quite old, but I got this to work with minimal disturbance to my code
Change binder.setValidator(new DualEntryValidator());
to
#InitBinder
protected void initBinder(WebDataBinder binder) {
binder.addValidators(new DualEntryValidator());
}
With setValidator() you're replacing the JSR-303 validator with your one. With addValidator(), the JSR-303 validator is called and so is yours.
You need to make sure that your validator does not overlap with your JSR-303 #NotNull, #Min, #Max, etc. annotations otherwise you'll get duplicate error messages added.
Spring provides three handle for bean validation.
1.abstract class AbstractPropertyValidationAnnotationHandler
2.abstract class AbstractMethodValidationAnnotationHandler
3.abstract class ClassValidationAnnotationHandler
In this example i am implementing custom annotation CustomAnnotationHandle
#Target({ElementType.METHOD, ElementType.TYPE})
#Retention(RetentionPolicy.RUNTIME)
#Documented
Class CustomAnnotationHandle extends Annotation{
public abstract String value();
}
To implement custom annotation for property validation we need to extend AbstractPropertyValidationAnnotationHandler Class.
AbstractPropertyValidationAnnotationHandler provides createValidationRule abstract method
protected abstract AbstractValidationRule createValidationRule(Annotation annotation, Class class1, String s);
So,the extended class must provide implementation of
protected abstract AbstractValidationRule createValidationRule(Annotation annotation, Class class1, String s)
public class CustomPropertyAnnotationHandler extends AbstractPropertyValidationAnnotationHandler
{
public CustomPropertyAnnotationHandler()
{
super(new Class[] {
XXX.XXX.PackageLevle.CustomAnnotationHandle // as it takes array of custom annotation ,so we can pass more than one
// overwriting abstract method
protected AbstractValidationRule createValidationRule(Annotation annotation, Class class1, String s){
CustomAnnotationHandle value = (CustomAnnotationHandle)annotation;
return TestValidationRule(value.getValue());
// as you can see it return AbstractValidationRule.So, we need a class to give our bean specific validation rule.In our case it is
//TestValidationRule
}
}
}
public class TestValidationRule extends AbstractValidationRule
{
public TestValidationRule (String valuetest)
{
super();
this.valuetest = valuetest;
}
Private String valuetest;
}
Spring provides AnnotationBeanValidationConfigurationLoader Class.This class is used for spring own annotation for bean validation.
DefaultValidationAnnotationHandlerRegistry class is used as defaultHandlerRegistry.But if we need to provide our own annotaion then we
need to extend AnnotationBeanValidationConfigurationLoader and set our specific handleregistry via method
setHandlerRegistry(new CustomPropertyAnnotationHandler());
Class DefaultValidationAnnotationHandlerRegistry is used to register spring own annotation for bean validation.It register bean by
calling registerPropertyHandler method of SimpleValidationAnnotationHandlerRegistry class.So for our custom annotation we need to
register CustomPropertyAnnotationHandler by calling registerPropertyHandler method of SimpleValidationAnnotationHandlerRegistry class
public class OurBeanSpecificValidationLoader extends AnnotationBeanValidationConfigurationLoader
{
public OurBeanSpecificValidationLoader ()
{
super();
setHandlerRegistry(new OurSpecificAnnotationHandleRegistery ());
}
}
public class OurSpecificAnnotationHandleRegistery extends DefaultValidationAnnotationHandlerRegistry
{
public OurSpecificAnnotationHandleRegistery ()
{
registerPropertyHandler(new CustomPropertyAnnotationHandler() );
}
}
so you have your custom annotation for bean valiation.E.g
#CustomAnnotationHandle(value = "test")
private Object test;

Resources