Spring annotation in Controller don't work? None of #Secure and #Async works - spring

I use spring-roo to generate my project. I don't know these 2 things are related or not, but in Controller, none of the annotation #Async or #Secure works.
For #Secure:
I added <global-method-security secured-annotations="enabled"/> tag to applicationContext-security.xml and modified the pom.xml to meet dependency,
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-aspects</artifactId>
<version>3.0.5.RELEASE</version>
</dependency>
above the method in the controller, I added #Secured("ROLE_ADMIN") but no matter what role everybody can access the method. Anything I missed to configure to make the #Secure Active?
For #Async:
In applicationContext.xml, I added
<task:annotation-driven executor="asyncExecutor"/>
<task:executor id="asyncExecutor" pool-size="${executor.poolSize}"/>
in controller.java:
#Async
private void justWait20seconds() {
try {
Thread.sleep(20000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
I expect this method will not block the main method, but it didn't. These 2 tag are all in my UserController.java, I don't know whether they are linked. Can anyone help?

It sounds like you don't understand how Spring contexts are organized in a Spring MVC application and are adding the annotation processing instructions to the wrong context. Do some reading on Spring contexts in Spring MVC. You can find another SO answer of mine that branches to other related answers at: Why DispatcherServlet creates another application context?

I had the same problem in which security annotations worked in a Roo project's jspx's but not in the controllers. My fix was to add the following to webmvc-config.xml:
<security:global-method-security secured-annotations="enabled" />
(adding this to applicationContext-security.xml did NOT work for me)
Then I added dependency for cglib in the pom.xml:
<dependency>
<groupId>cglib</groupId>
<artifactId>cglib</artifactId>
<version>2.2</version>
</dependency>

Related

What kind of view technology used in spring boot by default

What kind of view technology used in spring boot by default when I add the 'Spring Boot Web Starter'.
If I want to use the JSP, I need to include the 'tomcat-embed-jasper' or 'Spring Boot Thymeleaf Starter' for thymeleaf templates. So I would like to know the default view technology of 'Spring Boot Web Starter'
By default there is no view You need to configure and add their dependencies.If You are using Spring Boot older versions then You can refer above answer but if You are using Spring Boot 2 then add on more dependency for thymeleaf-
<dependency>
<groupId>nz.net.ultraq.thymeleaf</groupId>
<artifactId>thymeleaf-layout-dialect</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
JSP is supported by Spring out-of-the-box.
It can be configured like this
#EnableWebMvc
#Configuration
public class ApplicationConfiguration implements WebMvcConfigurer {
#Bean
public ViewResolver jspViewResolver() {
InternalResourceViewResolver bean = new InternalResourceViewResolver();
bean.setPrefix("/WEB-INF/views/");
bean.setSuffix(".jsp");
return bean;
}
}
or in properties file
spring.mvc.view.prefix: /WEB-INF/views/
spring.mvc.view.suffix: .jsp
For Thymeleaf
Spring Boot will provide auto-configuration for Thymeleaf with below dependency in pom.xml
Please make a note of version used. Also you might need to provide view properties like above
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
<version>1.5.6.RELEASE</version>
</dependency>

Following Spring 5 webmvc Rest service guide - No converter found for return value of type

I am following the official guide for Building a RESTful Web Service from Spring.io
In short, I'm following the above guide but using Tomcat to deploy and execute.
I've looked at some SO questions and answers regarding this issue.
Spring Boot Application: No converter found for return value of type
and some others.
I have the getter methods in the Greeting class though I don't have setters. This is exactly how the class is on the guide.
I tried adding the fasterxml json dependency on my pom.xml but the error message is the same.
All my setup is exactly the same as the guide except the app is bootstrapped by a dispatch-servlet.xml instead of a main method.
web.xml
<servlet>
<servlet-name>greeting</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>greeting</servlet-name>
<url-pattern>/greeting/*</url-pattern>
</servlet-mapping>
greeting-servlet.xml
<context:component-scan base-package="com.test" />
This is it. All the other classes are written exactly the same as the guide. with #RestController and no #ResponseBody as #RestController is rolled out with #Controller and #ResponseBody according to the guide itself.
This is my error message.
WARNING: Failed to write HTTP message: org.springframework.http.converter.HttpMessageNotWritableException: No converter found for return value of type: class com.test.Greeting
I don't think it's the issue with getters( I definitely have them).
Nor it's the issue with not having the fasterxml dependency.
What am I missing?
You definitely need the main method:
#SpringBootApplication
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
The #SpringBootApplication annotation does more than you think. The most important thing is that it calls#EnableAutoConfiguration. This is used to figures out which other dependencies you do in your project. In your case that annotation would configure Jackson to parse your Java object to JSON.
Directly from the JavaDoc:
Enable auto-configuration of the Spring Application Context,
attempting to guess and configure beans that you are likely to need.
Auto-configuration classes are usually applied based on your classpath
and what beans you have defined. For example, If you have
tomcat-embedded.jar on your classpath you are likely to want a
TomcatEmbeddedServletContainerFactory (unless you have defined your
own EmbeddedServletContainerFactory bean).
If you still think creating a war file is a good idea, check if this can help you setup Jackson with plain Spring.
EDIT: How to run Spring Boot without Tomcat
You could check this out, the doc says to do this:
..
<packaging>war</packaging>
..
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
<scope>provided</scope>
</dependency>
And in theory you should be good to go, BUT that might not be the case so check out the sample project from Spring.
These people also got some issues, so check out if it also effects you.

How to inject a bean into JAX RS resource?

I am sure this is most probably a silly question but I am not familiar with JAX RS (and Jersey).
We've had a standalone Java application that basically starts a RESTful service. As part of a refactoring, we've moved this application to be just a thread within another application. That other application uses Spring beans that are defined in an application-context.xml. So, I need to inject some of those beans to the resource class (if that's the correct name for it: the one with #Path annotations, etc.). The problem is I don't know what instantiates this particular class. There is a main class of the legacy app that is creating a (jetty) Server instance with ServletContexthandler to which a ServletHolder is added to which a ResourceConfig is set. Something like that.
So, I can inject my stuff from Spring to this main class but can't see how exactly I can pass those objects to the JAX RS resource?
I am sure I miss something pretty simple.
Edit: I have added a better explanation to my problem and a solution I found below.
Jersey has integration with Spring support. For this case, there are really only two things you need to do:
Make sure you have the integration dependency. You'll also need to the commons logging, so it doesn't complain
<dependency>
<groupId>org.glassfish.jersey.ext</groupId>
<artifactId>jersey-spring4</artifactId>
</dependency>
<dependency>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
<version>1.1</version>
<exclusions>
<exclusion>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
</exclusion>
</exclusions>
</dependency>
Just add a ContextLoaderListener along with a WebApplicationContext containing your Spring context configuration.
ServletContextHandler context
= new ServletContextHandler(ServletContextHandler.SESSIONS);
AnnotationConfigWebApplicationContext wac
= new AnnotationConfigWebApplicationContext();
wac.register(SpringConfig.class);
context.addEventListener(new ContextLoaderListener(wac));
Here the SpringConfig is just a "Java config" Spring configuration class. If you wanted you could use an XML application context, but the example I used in the below link uses a Java config class, but also show how to easily import an XML into the class if you just want to use your XML config. You can combine two.
That's pretty much it. Once you have this configured, you should be able to #Autowired your Spring beans into your Jersey resources.
For a complete example, check out this GitHub repo
Maybe I wasn't able to explain well my problem, so basically it was a problem of how to inject beans into JAX-RS resource classes when the actual JAX-RS app is not being instantiated through its own DI-mechanism but from somewhere else. In my case I already had a Spring container that creates those beans and there was no easy way to link the Spring's own bean application context to the JAX-RS's one. A better solution would have been the one already answered but additional problem is that our existing Spring solution is XML-based, whereas the #Injected annotation in JAX-RS won't work with it (at least that's what I've read in their documentation).
So, JAX-RS supports #Injected annotations and in order for it to know where to get bean definitions from, I had to go to the class that defines the ResourceConfig and add the following lines to it:
.register(new AbstractBinder() {
#Override
protected void configure() {
bind(beanImpl1).to(BeanInterface1.class);
bind(beanImpl2).to(BeanInterface2.class);
}
})
The actual beanImpl1 and beanImpl2 bean instances were coming through the constructor of that class, which in turn was instantiated from our Spring through the XML configuration.

Springboot security access per field

I would like to make access per field in spring mvc.
For example
I got entity with 3 fields
id,name,description.
User with ROLE_USER can see only name and user who got ROLE_ADMIN can see name and description. I tried to use
#PreAuthorize("hasRole('ROLE_USER')") in entity and dto but its only work in service and controller.
I tried to use #Component adonation before #Entity but it doesnt work.
ps: prePostEnabled is configured
#EnableGlobalMethodSecurity(prePostEnabled = true)
any solutions?
For this propouse a better approach is use the spring security tag if you are using jsp or thymeleaf spring security dialect if you are using thymeleaf.
in the first case you have this maven dependency in your pom
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-taglibs</artifactId>
<version>your.version</version>
</dependency>
in the second case you have this maven dependency in your pom
<dependency>
<groupId>org.thymeleaf.extras</groupId>
<artifactId>thymeleaf-extras-springsecurity4</artifactId>
<version>your.version</version>
</dependency>
the key point hear is that with #EnableGlobalMethodSecurity you are working at method security protection and not at presentation level protection. In other words with your configuration you can protect the your method calling at application level in base of how the Security contect is popolated while for a presentation protection Spring security provide some custom tag for acive this propouse, for thymeleaf you can use the security dialect.
I hope that this can help you

JMX on Spring Boot project

I have annotated a class as follows:
#ManagedResource(objectName="com.myproject.bean.jmx:name=JMXSolrIndexerBean",
description="Index Solr Operations")
public class JMXSolrIndexerBean {
....
}
My pom has the following dependencies
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.integration</groupId>
<artifactId>spring-integration-jmx</artifactId>
<version>4.1.6.RELEASE</version>
</dependency>
I can't find my MBean in the JConsole... are there any configuration steps I am missing?
Two things:
You don't need the spring-integrtation-jmx dependency to make that work, the actuator starter is enough
Your class needs to be a spring bean if you want Spring Boot to auto-detect JMX annotation on them. So adding #Component on your JMXSolrIndexerBean is all that's needed as long as it is located in a package that is processed by component scan
In other words, that class of yours is just a pojo that spring know nothings about. #ManagedResource is not a stereotype that turns that class in a Spring Bean.

Resources