What is order of evaluation for #Autowiring in SpringBoot project - spring-boot

I'm trying to write a simple SprintBoot REST Controller to run on Websphere Liberty, and having a problem with #Autowire. Here are the relevant (I think) pieces of code:
#CrossOrigin
#RestController
#RequestMapping(path = "userSetting")
public class RESTInterface {
#Autowired
private UserSettingDAO userSettingDAO;
#RequestMapping(path = "/getUserSetting", method = { RequestMethod.GET }, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
public String getUserSetting(
#RequestParam(value="user_id", required=true ) String user_id,
#RequestParam(value="app_id", required=true ) String app_id,
#RequestParam(value="dashboard_name", required=true ) String dashboard_name
) {
if ( userSettingDAO == null ) {
System.out.println( "userSettingDAO is null" );
...
////////////////////////////////////////////////////////////////////////////////
#Component
public class UserSettingDAO {
#Autowired
private JdbcTemplate jdbcTemplate;
#Autowired
private DataSource dataSource;
public UserSettingDAO() {
System.out.println( "dataSource is " + dataSource );
System.out.println( "jdbcTemplate is " + jdbcTemplate );
When I deploy the application to Liberty, it appears to start up OK.
When I hit the appropriate endpoint, I see the following in console.log:
UserSettingDAO.jdbcTemplate = null
dataSource is null
jdbcTemplate is null
2018-04-24 16:54:19.887 INFO 8807 --- [cutor-thread-11] s.w.s.m.m.a.RequestMappingHandlerMapping : Mapped "{[/userSetting/getUserSetting],methods=[GET],produces=[application/json;charset=UTF-8]}" onto public java.lang.String com.ui.usersetting.restinterface.RESTInterface.getUserSetting(java.lang.String,java.lang.String,java.lang.String)
2018-04-24 16:54:19.890 INFO 8807 --- [cutor-thread-11] s.w.s.m.m.a.RequestMappingHandlerMapping : Mapped "{[/userSetting/upsertUserSetting],methods=[POST],produces=[application/json;charset=UTF-8]}" onto public void com.ui.usersetting.restinterface.RESTInterface.upsertUserSetting(java.lang.String,java.lang.String,java.lang.String,java.lang.String)
2018-04-24 16:54:19.891 INFO 8807 --- [cutor-thread-11] s.w.s.m.m.a.RequestMappingHandlerMapping : Mapped "{[/userSetting/deleteUserSetting],methods=[DELETE],produces=[application/json;charset=UTF-8]}" onto public void com.ui.usersetting.restinterface.RESTInterface.deleteUserSetting(java.lang.String,java.lang.String,java.lang.String)
2018-04-24 16:54:19.893 INFO 8807 --- [cutor-thread-11] s.w.s.m.m.a.RequestMappingHandlerMapping : Mapped "{[/userSetting/hello],methods=[GET],produces=[application/json;charset=UTF-8]}" onto public java.lang.String com.ui.usersetting.restinterface.RESTInterface.hello()
2018-04-24 16:54:19.924 INFO 8807 --- [cutor-thread-11] s.w.s.m.m.a.RequestMappingHandlerMapping : Mapped "{[/error],produces=[text/html]}" onto public org.springframework.web.servlet.ModelAndView org.springframework.boot.autoconfigure.web.servlet.error.BasicErrorController.errorHtml(javax.servlet.http.HttpServletRequest,javax.servlet.http.HttpServletResponse)
2018-04-24 16:54:19.925 INFO 8807 --- [cutor-thread-11] s.w.s.m.m.a.RequestMappingHandlerMapping : Mapped "{[/error]}" onto public org.springframework.http.ResponseEntity<java.util.Map<java.lang.String, java.lang.Object>> org.springframework.boot.autoconfigure.web.servlet.error.BasicErrorController.error(javax.servlet.http.HttpServletRequest)
2018-04-24 16:54:20.166 INFO 8807 --- [cutor-thread-11] s.w.s.m.m.a.RequestMappingHandlerAdapter : Looking for #ControllerAdvice: org.springframework.boot.web.servlet.context.AnnotationConfigServletWebServerApplicationContext#6a5997f7: startup date [Tue Apr 24 16:54:15 EDT 2018]; root of context hierarchy
2018-04-24 16:54:21.386 INFO 8807 --- [cutor-thread-11] o.s.j.e.a.AnnotationMBeanExporter : Registering beans for JMX exposure on startup
2018-04-24 16:54:21.389 INFO 8807 --- [cutor-thread-11] o.s.j.e.a.AnnotationMBeanExporter : Bean with name 'dataSource' has been autodetected for JMX exposure
2018-04-24 16:54:21.396 INFO 8807 --- [cutor-thread-11] o.s.j.e.a.AnnotationMBeanExporter : Located MBean 'dataSource': registering with JMX server as MBean [com.zaxxer.hikari:name=dataSource,type=HikariDataSource]
My question is: Why are the two println statements saying that their respective variables are null? Does it have something to do with the fact that the UserSettingDAO constructor appears in the log to be executed before the lines about dataSource appear in the log?
What should I do to get those variables properly initialized?

At the time a Spring component's constructor is called, any #Autowired objects will still be null. This is because the spring container needs to initialize an instance of the class before it can inject values into the #Autowired fields.
I don't know how Spring implements injection, but most Java injection works something like this:
Construct new instance of the bean class, normally by invoking default ctor (or initializing a dynamically generated sub-class proxy)
Obtain objects that need to be injected into the bean
Using reflection/proxy, set the fields on the bean
To validate this, I created a method on UserSettingsDAO that utilizes the #AutoWired fields:
#Component
public class UserSettingDAO {
#Autowired
private JdbcTemplate jdbcTemplate;
#Autowired
private DataSource ds;
public UserSettingDAO() {
System.out.println("ctor/jdbcTemplate is " + jdbcTemplate );
System.out.println("ctor/datasource is: " + ds);
}
public void doStuff() {
System.out.println("doStuff/jdbcTemplate is " + jdbcTemplate );
System.out.println("doStuff/datasource is: " + ds);
}
}
If we inject this DAO into another class and use it, we will see that the fields are initialized after the UserSettingDAO is constructed:
#CrossOrigin
#RestController
public class RESTInterface {
#Autowired
private UserSettingDAO dao;
#RequestMapping(path = "/jdbc", method = { RequestMethod.GET }, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
public String jdbc() {
return dao.doStuff();
}
}
Checking logs, this will produce the following output:
ctor/jdbcTemplate is null
ctor/datasource is: null
doStuff/jdbcTemplate is org.springframework.jdbc.core.JdbcTemplate#4eb46bed
doStuff/datasource is: com.ibm.ws.rsadapter.jdbc.WSJdbcDataSource#727d23c5

Related

running the application on controller

I'm still a beginner with spring boot, I'm using spring JPA to fetch the data from multiple tables in the same database and everything going fine, I used to run my application at the Main but here I have added a Controller class and running things there, then i used #Scheduled(fixedRate=7000) instead of creating an infinite loop to keep check the data from db and stay live, the application working fine but as far as at the running time application executed twice instead of once at the beginning before scheduling, a is there any idea about what happened here :
Mainclass :
#SpringBootApplication
#EnableScheduling
public class AccessingDataJpaApplication {
public static void main(String[] args) throws Exception{
SpringApplication.run(AccessingDataJpaApplication.class);
}
}
Controller class :
#Controller
#EnableScheduling
public class MainController {
private static final Logger logger = LoggerFactory.getLogger(MainController.class);
#Autowired
private CustomerRepository customerRepository;
#Autowired
private MessageRepository messageRepository;
private Set<String> camps = new HashSet<String>();
#Bean
#Scheduled(fixedRate=7000)
public void run(){
logger.info("Running");
if((customerRepository.findAllByStatusAndCampType(0, 1).size()) > 0 ){
for(Customer customer : customerRepository.findAll()){
System.out.println(customer.getCampCd());
camps.add(customer.getCampCd());
}
System.out.println("----------------------------------------");
for(MessageCampain messagecampain : messageRepository.findAllByCampCdIn(camps)) {
System.out.println(messagecampain.toString());
}
System.out.println("------------------------------------------");
for(String value : camps) {
System.out.println(value);
}
}
}
}
execution log :
[ main] org.hibernate.dialect.Dialect : HHH000400: Using dialect: org.hibernate.dialect.MySQL5Dialect
[ main] o.h.e.t.j.p.i.JtaPlatformInitiator : HHH000490: Using JtaPlatform implementation: [org.hibernate.engine.transaction.jta.platform.internal.NoJtaPlatform]
[ main] j.LocalContainerEntityManagerFactoryBean : Initialized JPA EntityManagerFactory for persistence unit 'default'
[ main] j.LocalContainerEntityManagerFactoryBean : Initialized JPA EntityManagerFactory for persistence unit 'default'
[ main] c.e.accessingdatajpa.MainController : Running
[ main] o.s.s.c.ThreadPoolTaskScheduler : Initializing ExecutorService 'taskScheduler'
[ main] c.e.a.AccessingDataJpaApplication : Started AccessingDataJpaApplication in 5.467 seconds (JVM running for 6.242)
[ scheduling-1] c.e.accessingdatajpa.MainController : Running
[ scheduling-1] c.e.accessingdatajpa.MainController : Running
you can notice that at Running word
It is because you annotate the run() in MainController as #Bean , which will creates a lite mode bean called run. (Spring represents this bean as the type of NullBean internally)
So , the 1st call of 'Running' in the main thread is due to spring instantiate this run bean. The remaining calls of 'Running' in the scheduling-1 thread are due to the the effect of #Scheduled. So please remove #Bean from the run() as it does not have any points to create a null bean ...
#Scheduled(fixedRate=7000)
public void run(){
}

Spring - How to build a junit test for a soap service

I'm following the spring guide to create a hello world soap ws. The link below :
https://spring.io/guides/gs/producing-web-service/
I successfully make it work. When i run this command line :
curl --header "content-type: text/xml" -d
#src/test/resources/request.xml http://localhost:8080/ws/coutries.wsdl
I get this response.
<SOAP-ENV:Header/><SOAP-ENV:Body><ns2:getCountryResponse xmlns:ns2="http://spring.io/guides/gs-producing-web-service"><ns2:country><ns2:name>Spain</ns2:name><ns2:population>46704314</ns2:population><ns2:capital>Madrid</ns2:capital><ns2:currency>EUR</ns2:currency></ns2:country></ns2:getCountryResponse></SOAP-ENV:Body></SOAP-ENV:Envelope>
Now i'm trying to create a junit test for this service (the controller layer) but it doesn't work.
Here is my unit test :
#RunWith(SpringRunner.class)
#WebMvcTest(CountryEndpoint.class)
#ContextConfiguration(classes = {CountryRepository.class, WebServiceConfig.class})
public class CountryEndpointTest {
private final String URI = "http://localhost:8080/ws/countries.wsdl";
#Autowired
private MockMvc mockMvc;
#Test
public void test() throws Exception {
mockMvc.perform(
get(URI)
.accept(MediaType.TEXT_XML)
.contentType(MediaType.TEXT_XML)
.content(request)
)
.andDo(print())
.andExpect(status().isOk());
}
static String request = "<soapenv:Envelope xmlns:soapenv=\"http://schemas.xmlsoap.org/soap/envelope/\"\n" +
" xmlns:gs=\"http://spring.io/guides/gs-producing-web-service\">\n" +
" <soapenv:Header/>\n" +
" <soapenv:Body>\n" +
" <gs:getCountryRequest>\n" +
" <gs:name>Spain</gs:name>\n" +
" </gs:getCountryRequest>\n" +
" </soapenv:Body>\n" +
"</soapenv:Envelope>";
}
here's the error :
MockHttpServletResponse:
Status = 404
Error message = null
Headers = {}
Content type = null
Body =
Forwarded URL = null
Redirected URL = null
Cookies = []
java.lang.AssertionError: Status
Expected :200
Actual :404
I changed the log level to debug and i found this :
2020-01-27 18:04:11.880 INFO 32723 --- [ main] c.s.t.e.s.endpoint.CountryEndpointTest : Started CountryEndpointTest in 1.295 seconds (JVM running for 1.686)
2020-01-27 18:04:11.925 DEBUG 32723 --- [ main] s.w.s.m.m.a.RequestMappingHandlerMapping : Looking up handler method for path /ws/countries.wsdl
2020-01-27 18:04:11.929 DEBUG 32723 --- [ main] s.w.s.m.m.a.RequestMappingHandlerMapping : Did not find handler method for [/ws/countries.wsdl]
2020-01-27 18:04:11.930 DEBUG 32723 --- [ main] o.s.w.s.handler.SimpleUrlHandlerMapping : Matching patterns for request [/ws/countries.wsdl] are [/**]
2020-01-27 18:04:11.930 DEBUG 32723 --- [ main] o.s.w.s.handler.SimpleUrlHandlerMapping : URI Template variables for request [/ws/countries.wsdl] are {}
2020-01-27 18:04:11.931 DEBUG 32723 --- [ main] o.s.w.s.handler.SimpleUrlHandlerMapping : Mapping [/ws/countries.wsdl] to HandlerExecutionChain with handler [ResourceHttpRequestHandler [locations=[ServletContext resource [/], class path resource [META-INF/resources/], class path resource [resources/], class path resource [static/], class path resource [public/]], resolvers=[org.springframework.web.servlet.resource.PathResourceResolver#c7a977f]]] and 1 interceptor
I tried another solution (below) but it doesn't work either.
#RunWith(SpringRunner.class)
#ContextConfiguration(classes = {WebServiceConfig.class, CountryRepository.class})
public class CountryEndpointTest {
private final String URI = "http://localhost:8080/ws/countries.wsdl";
private MockMvc mockMvc;
#Autowired
CountryRepository countryRepository;
#Before
public void setup() {
this.mockMvc = standaloneSetup(new CountryEndpoint(countryRepository)).build();
}
Spring doc says :
https://docs.spring.io/spring-boot/docs/2.1.5.RELEASE/reference/html/boot-features-testing.html
By default, #SpringBootTest will not start a server.
You need to define
#SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
to RUN the server.
I tried with mockserver, but I can't access to the endpoint (even with WebEnvironment.DEFINED_PORT)
So I did it as follow :
#RunWith(SpringRunner.class)
#ActiveProfiles("test")
#SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
#AutoConfigureWebTestClient
public class FacturationEndpointTest {
#Autowired
private WebTestClient webClient;
#Test
public void testWSDL() throws Exception {
this.webClient.get().uri("/test_service/services.wsdl")
.exchange().expectStatus().isOk();
}
You need to add the following dependency in your pom.xml if you want to use WebTestClient like me :
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-webflux</artifactId>
<scope>test</scope>
</dependency>
Please change the GET method to POST.
mockMvc.perform(
postURI) // <-- This line!!!
.accept(MediaType.TEXT_XML)
.contentType(MediaType.TEXT_XML)
.content(request)
if you are using a spring ws framework to implements your endpoints, please see spring-ws-test. you will find a MockWebServiceClient that mocks a client and tests your endpoint. I propose you to see this example : https://memorynotfound.com/spring-ws-server-side-integration-testing/
this works only for spring web service and not for CXF web services.

#Cacheable and initialization during startup

I would like to initialize all entries in cache during startup of my spring boot application (loading stuff from DB). Ideally, this is done before the application is already ready. So I implemented all loading in #PostConstruct. I remarked, that the cache is not already setup in #PostContruct and I followed some tips to do such initializations in the ApplicationReadyEvent. However, this still does not work as expected:
Even though I already call a #Cacheable Method in ApplicationReadyEvent, the second invocation re-enters the method instead of using the cache.
My Service:
#Service
public class MyService implements ApplicationListener<ApplicationReadyEvent {
#Cacheable("entry")
public List<String> getEntry() {
System.out.println("getEntry called!");
return Arrays.asList("aaa", "bbb");
}
#Override
public void onApplicationEvent(ApplicationReadyEvent applicationReadyEvent) {
System.out.println("*** onApplicationEvent");
getEntry();
}
}
My Caffeine CacheManager Config:
#Configuration
#EnableCaching
public class CachingConfig {
#Bean
public CacheManager cacheManager() {
List<CaffeineCache> caffeineCaches = chacheList(Arrays.asList(
"entry"
));
SimpleCacheManager simpleCacheManager = new SimpleCacheManager();
simpleCacheManager.setCaches(caffeineCaches);
System.out.println("*** #Bean CacheManager");
return simpleCacheManager;
}
private List<CaffeineCache> chacheList(List<String> cacheNames) {
return cacheNames.stream().map(s -> new CaffeineCache(s, Caffeine.newBuilder().build()))
.collect(Collectors.toList());
}
}
A simple REST endpoint using the service:
#RestController
public class MyController {
#Autowired
MyService myService;
#GetMapping("/test")
public void test()
{
System.out.println("*** GET /test");
myService.getEntry();
}
}
If I start the application and perform two GET /test, I get the following output:
INFO 20120 --- [ main] o.s.web.context.ContextLoader : Root WebApplicationContext: initialization completed in 907 ms
*** #Bean CacheManager
INFO 20120 --- [ main] o.s.s.concurrent.ThreadPoolTaskExecutor : Initializing ExecutorService 'applicationTaskExecutor'
INFO 20120 --- [ main] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat started on port(s): 8080 (http) with context path ''
INFO 20120 --- [ main] com.example.demo.DemoApplication : Started DemoApplication in 1.639 seconds (JVM running for 2.473)
*** onApplicationEvent
*** getEntry called!
INFO 20120 --- [nio-8080-exec-1] o.a.c.c.C.[Tomcat].[localhost].[/] : Initializing Spring DispatcherServlet 'dispatcherServlet'
INFO 20120 --- [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet : Initializing Servlet 'dispatcherServlet'
INFO 20120 --- [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet : Completed initialization in 4 ms
*** GET /test
*** getEntry called!
*** GET /test
So why does the second invocation of MyService.getEntry (i.e. the first invocation after "Startup") enters the code again?
At the end, I need a solution, which performs the first loading before the application finished to startup - i.e. I will try ContextRefreshedEvent or again #PostConstruct (and #Autowire CacheManager to have it configured before executing #PostConstruct). But the first step would be to get this example here behave as expected.
Ok, stupid error: in my service, the call to getEntry() must be done over proxy object rather than directly:
#Service
public class MyService implements ApplicationListener<ApplicationReadyEvent {
#Autowired
MyService self;
#Cacheable("entry")
public List<String> getEntry() {
System.out.println("getEntry called!");
return Arrays.asList("aaa", "bbb");
}
#Override
public void onApplicationEvent(ApplicationReadyEvent applicationReadyEvent) {
System.out.println("*** onApplicationEvent");
self.getEntry();
}
}

Custom RequestMappingHandlerMapping causes an error with Swagger

I have created a custom RequestMappingHandlerMapping with the latest version of Spring as follows so I can define a custom version annotation.
WebConfiguration,
#Configuration
#ConditionalOnClass({ ApiVersionedResource.class })
public class WebConfiguration {
#Bean
#Primary
public ContentNegotiationManager contentNegotiationManager() {
ContentNegotiationManagerFactoryBean contentNegotiationManagerFactoryBean = new ContentNegotiationManagerFactoryBean();
Map<String, MediaType> mediaTypes = new HashMap<>();
mediaTypes.put("json", MediaType.APPLICATION_JSON);
contentNegotiationManagerFactoryBean.addMediaTypes(mediaTypes);
contentNegotiationManagerFactoryBean.afterPropertiesSet();
return contentNegotiationManagerFactoryBean.getObject();
}
#Bean
public WebMvcRegistrationsAdapter webMvcRegistrationsHandlerMapping() {
return new WebMvcRegistrationsAdapter() {
#Override
public RequestMappingHandlerMapping getRequestMappingHandlerMapping() {
CustomRequestMappingHandlerMapping handlerMapping = new CustomRequestMappingHandlerMapping();
handlerMapping.setOrder(0);
handlerMapping.setRemoveSemicolonContent(false);
handlerMapping.setContentNegotiationManager(contentNegotiationManager());
return handlerMapping;
}
};
}
}
CustomRequestMappingHandlerMapping,
public class CustomRequestMappingHandlerMapping extends RequestMappingHandlerMapping {
#Override
protected RequestCondition<?> getCustomTypeCondition(Class<?> handlerType) {
ApiVersionedResource typeAnnotation = AnnotationUtils.findAnnotation(handlerType, ApiVersionedResource.class);
return createCondition(typeAnnotation);
}
#Override
protected RequestCondition<?> getCustomMethodCondition(Method method) {
ApiVersionedResource methodAnnotation = AnnotationUtils.findAnnotation(method, ApiVersionedResource.class);
return createCondition(methodAnnotation);
}
#Override
protected boolean isHandler(Class<?> beanType) {
return super.isHandler(beanType) && (AnnotationUtils.findAnnotation(beanType, ApiVersionedResource.class) != null);
}
private RequestCondition<?> createCondition(ApiVersionedResource versionMapping) {
if (versionMapping != null) {
return new ApiVersionedResourceRequestCondition(versionMapping.media(), versionMapping.version());
}
return null;
}
}
However, this is causing the following error during compilation and I have no idea what is causing it.
2017-03-15 16:44:58.215 DEBUG 63518 --- [ restartedMain] r.h.v.CustomRequestMappingHandlerMapping : 6 request handler methods found on class com.test.web.rest.OrganizationResource: {public org.springframework.http.ResponseEntity com.test.web.rest.OrganizationResource.createOrganization(com.test.service.dto.OrgDetailsDTO) throws java.net.URISyntaxException={[/organizations],methods=[POST],custom=[API Versions = {media=application/vnd.test.onboarding, versions=[]}]}, public org.springframework.http.ResponseEntity com.test.web.rest.OrganizationResource.updateOrganization(com.test.service.dto.OrgDetailsDTO) throws java.net.URISyntaxException={[/organizations],methods=[PUT],custom=[API Versions = {media=application/vnd.test.onboarding, versions=[]}]}, public org.springframework.http.ResponseEntity com.test.web.rest.OrganizationResource.getAllOrganizations(org.springframework.data.domain.Pageable) throws java.net.URISyntaxException={[/organizations],methods=[GET],custom=[API Versions = {media=application/vnd.test.onboarding, versions=[]}]}, public org.springframework.http.ResponseEntity com.test.web.rest.OrganizationResource.deleteOrganization(java.lang.Long)={[/organizations/{id}],methods=[DELETE],custom=[API Versions = {media=application/vnd.test.onboarding, versions=[]}]}, public org.springframework.http.ResponseEntity com.test.web.rest.OrganizationResource.searchOrganizations(java.lang.String,org.springframework.data.domain.Pageable) throws java.net.URISyntaxException={[/search/organizations],methods=[GET],custom=[API Versions = {media=application/vnd.test.onboarding, versions=[]}]}, public org.springframework.http.ResponseEntity com.test.web.rest.OrganizationResource.getOrganization(java.lang.Long)={[/organizations/{id}],methods=[GET],custom=[API Versions = {media=application/vnd.test.onboarding, versions=[]}]}}
2017-03-15 16:44:58.238 INFO 63518 --- [ restartedMain] r.h.v.CustomRequestMappingHandlerMapping : Mapped "{[/organizations],methods=[POST],custom=[API Versions = {media=application/vnd.test.onboarding, versions=[]}]}" onto public org.springframework.http.ResponseEntity<com.test.service.dto.OrgDetailsDTO> com.test.web.rest.OrganizationResource.createOrganization(com.test.service.dto.OrgDetailsDTO) throws java.net.URISyntaxException
2017-03-15 16:44:58.239 INFO 63518 --- [ restartedMain] r.h.v.CustomRequestMappingHandlerMapping : Mapped "{[/organizations],methods=[PUT],custom=[API Versions = {media=application/vnd.test.onboarding, versions=[]}]}" onto public org.springframework.http.ResponseEntity<com.test.service.dto.OrgDetailsDTO> com.test.web.rest.OrganizationResource.updateOrganization(com.test.service.dto.OrgDetailsDTO) throws java.net.URISyntaxException
2017-03-15 16:44:58.239 INFO 63518 --- [ restartedMain] r.h.v.CustomRequestMappingHandlerMapping : Mapped "{[/organizations],methods=[GET],custom=[API Versions = {media=application/vnd.test.onboarding, versions=[]}]}" onto public org.springframework.http.ResponseEntity<java.util.List<com.test.service.dto.OrgDetailsDTO>> com.test.web.rest.OrganizationResource.getAllOrganizations(org.springframework.data.domain.Pageable) throws java.net.URISyntaxException
2017-03-15 16:44:58.239 INFO 63518 --- [ restartedMain] r.h.v.CustomRequestMappingHandlerMapping : Mapped "{[/organizations/{id}],methods=[DELETE],custom=[API Versions = {media=application/vnd.test.onboarding, versions=[]}]}" onto public org.springframework.http.ResponseEntity<java.lang.Void> com.test.web.rest.OrganizationResource.deleteOrganization(java.lang.Long)
2017-03-15 16:44:58.240 INFO 63518 --- [ restartedMain] r.h.v.CustomRequestMappingHandlerMapping : Mapped "{[/search/organizations],methods=[GET],custom=[API Versions = {media=application/vnd.test.onboarding, versions=[]}]}" onto public org.springframework.http.ResponseEntity<java.util.List<com.test.service.dto.OrgDetailsDTO>> com.test.web.rest.OrganizationResource.searchOrganizations(java.lang.String,org.springframework.data.domain.Pageable) throws java.net.URISyntaxException
2017-03-15 16:44:58.240 INFO 63518 --- [ restartedMain] r.h.v.CustomRequestMappingHandlerMapping : Mapped "{[/organizations/{id}],methods=[GET],custom=[API Versions = {media=application/vnd.test.onboarding, versions=[]}]}" onto public org.springframework.http.ResponseEntity<com.test.service.dto.OrgDetailsDTO> com.test.web.rest.OrganizationResource.getOrganization(java.lang.Long)
2017-03-15 16:44:58.314 WARN 63518 --- [ restartedMain] ationConfigEmbeddedWebApplicationContext : Exception encountered during context initialization - cancelling refresh attempt: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'documentationPluginsBootstrapper' defined in URL [jar:file:/Users/kasunt/.m2/repository/io/springfox/springfox-spring-web/2.6.1/springfox-spring-web-2.6.1.jar!/springfox/documentation/spring/web/plugins/DocumentationPluginsBootstrapper.class]: Unsatisfied dependency expressed through constructor parameter 1; nested exception is org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'webMvcRequestHandlerProvider' defined in URL [jar:file:/Users/kasunt/.m2/repository/io/springfox/springfox-spring-web/2.6.1/springfox-spring-web-2.6.1.jar!/springfox/documentation/spring/web/plugins/WebMvcRequestHandlerProvider.class]: Unsatisfied dependency expressed through constructor parameter 0; nested exception is org.springframework.beans.factory.BeanNotOfRequiredTypeException: Bean named 'requestMappingHandlerMapping' is expected to be of type 'org.springframework.web.servlet.mvc.method.RequestMappingInfoHandlerMapping' but was actually of type 'com.sun.proxy.$Proxy232'
Specially this right at the end,
***************************
APPLICATION FAILED TO START
***************************
Description:
The bean 'requestMappingHandlerMapping' could not be injected as a 'org.springframework.web.servlet.mvc.method.RequestMappingInfoHandlerMapping' because it is a JDK dynamic proxy that implements:
Action:
Consider injecting the bean as one of its interfaces or forcing the use of CGLib-based proxies by setting proxyTargetClass=true on #EnableAsync and/or #EnableCaching.
I seem to have fixed the problem by refactoring WebConfiguration as follows. Im not entirely sure why instantiating CustomRequestMappingHandlerMapping as a public class didn't work. Id be happy to listen to anyone who can think of a reason why.
#Configuration
#ConditionalOnClass({ ApiVersionedResource.class })
public class WebConfiguration {
#Bean
public WebMvcRegistrationsAdapter webMvcRegistrationsHandlerMapping() {
return new WebMvcRegistrationsAdapter() {
#Override
public RequestMappingHandlerMapping getRequestMappingHandlerMapping() {
return new CustomRequestMappingHandlerMapping();
}
};
}
private final class CustomRequestMappingHandlerMapping extends RequestMappingHandlerMapping {
#Override
protected RequestCondition<?> getCustomTypeCondition(Class<?> handlerType) {
ApiVersionedResource typeAnnotation = AnnotationUtils.findAnnotation(handlerType, ApiVersionedResource.class);
return createCondition(typeAnnotation);
}
#Override
protected RequestCondition<?> getCustomMethodCondition(Method method) {
ApiVersionedResource methodAnnotation = AnnotationUtils.findAnnotation(method, ApiVersionedResource.class);
return createCondition(methodAnnotation);
}
#Override
protected boolean isHandler(Class<?> beanType) {
return super.isHandler(beanType) && (AnnotationUtils.findAnnotation(beanType, ApiVersionedResource.class) != null);
}
private RequestCondition<?> createCondition(ApiVersionedResource versionMapping) {
if (versionMapping != null) {
return new ApiVersionedResourceRequestCondition(versionMapping.media(), versionMapping.version());
}
return null;
}
}
}
In Spring Boot 2.0.0, there is a simpler way to achieve this.
Create an instance of WebMvcRegistrations interface as a bean and override appropriate method to return the customized version of that object. Spring boot will read and use that instance.
In this case only the getRequestMappingHandlerMapping() needs to be overridden and a custom implementation returned

Spring Social -ConnecController connect/twitter not initiating connection with twitter

I have been working on integrating my project with twitter api,
connectController, which i have declared as bean in springsocialconfig, is perfectly handling get requests of /connect/twitter that's after including csrf token in jsp..... but when im about to send post request from connectTwitter.jsp its redirecting back to connectTwitter.jsp page viz how many times i hit the button.
No idea whats happening background , i have set up callback url as 127.0.0.1 in app settings
I am using Spring Mvc 4.2.5, Spring Security 4.0.4 , Spring Social 1.1.2
my springSocialConfiguration classs
#Configuration
#EnableSocial
#PropertySource(value = { "classpath:twitter.properties" })
public class SpringSocialConfig implements SocialConfigurer {
#Inject
private DataSource dataSource;
#Autowired
private Environment environment;
//
// SocialConfigurer implementation methods
//
#Override
public void addConnectionFactories(ConnectionFactoryConfigurer cfConfig, Environment env) {
cfConfig.addConnectionFactory(new TwitterConnectionFactory(environment.getProperty("twitter.consumerKey"), environment.getProperty("twitter.consumerSecret")));
}
#Override
public UserIdSource getUserIdSource() {
return new UserIdSource() {
#Override
public String getUserId() {
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
if (authentication == null) {
throw new IllegalStateException("Unable to get a ConnectionRepository: no user signed in");
}
return authentication.getName();
}
};
}
#Override
public UsersConnectionRepository getUsersConnectionRepository(ConnectionFactoryLocator connectionFactoryLocator) {
return new JdbcUsersConnectionRepository(dataSource, connectionFactoryLocator, Encryptors.noOpText());
}
//
// API Binding Beans
//
#Bean
#Scope(value="request", proxyMode=ScopedProxyMode.INTERFACES)
public Twitter twitter(ConnectionRepository repository) {
Connection<Twitter> connection = repository.findPrimaryConnection(Twitter.class);
return connection != null ? connection.getApi() : null;
}
//
// Web Controller and Filter Beans
//
#Bean
public ConnectController connectController(ConnectionFactoryLocator connectionFactoryLocator, ConnectionRepository connectionRepository) {
ConnectController connectController = new ConnectController(connectionFactoryLocator, connectionRepository);
return connectController;
}
#Bean
public ReconnectFilter apiExceptionHandler(UsersConnectionRepository usersConnectionRepository, UserIdSource userIdSource) {
return new ReconnectFilter(usersConnectionRepository, userIdSource);
}
}
my SecurityConfiguration class
#Configuration
#EnableWebSecurity
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
#Autowired
#Qualifier("customUserDetailsService")
UserDetailsService userDetailsService;
#Autowired
PersistentTokenRepository tokenRepository;
#Autowired
public void configureGlobalSecurity(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userDetailsService);
auth.authenticationProvider(authenticationProvider());
}
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.formLogin()
.loginPage("/login")
.loginProcessingUrl("/login")
.failureUrl("/login?param.error=bad_credentials").defaultSuccessUrl("/dashboard")
.usernameParameter("userName").passwordParameter("password").and()
.rememberMe().rememberMeParameter("remember-me").tokenRepository(tokenRepository)
.tokenValiditySeconds(86400)
.and()
.logout()
.logoutUrl("/signout")
.deleteCookies("JSESSIONID")
.and()
.authorizeRequests()
.antMatchers("/static/**", "/auth/**", "/login/**", "/signup/**","/","/home/**").permitAll()
.antMatchers("/**").authenticated();
}
#Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
#Bean
public TextEncryptor textEncryptor() {
return Encryptors.noOpText();
}
#Bean
public DaoAuthenticationProvider authenticationProvider() {
DaoAuthenticationProvider authenticationProvider = new DaoAuthenticationProvider();
authenticationProvider.setUserDetailsService(userDetailsService);
authenticationProvider.setPasswordEncoder(passwordEncoder());
return authenticationProvider;
}
#Bean
public PersistentTokenBasedRememberMeServices getPersistentTokenBasedRememberMeServices() {
PersistentTokenBasedRememberMeServices tokenBasedservice = new PersistentTokenBasedRememberMeServices(
"remember-me", userDetailsService, tokenRepository);
return tokenBasedservice;
}
#Bean
public AuthenticationTrustResolver getAuthenticationTrustResolver() {
return new AuthenticationTrustResolverImpl();
}
#Bean(name="authenticationManager")
#Override
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}
}
iam getting this on my console
INFO: Initializing Spring root WebApplicationContext
INFO : org.springframework.web.context.ContextLoader - Root WebApplicationContext: initialization started
INFO : org.springframework.web.context.support.AnnotationConfigWebApplicationContext - Refreshing Root WebApplicationContext: startup date [Thu Nov 24 16:11:21 IST 2016]; root of context hierarchy
INFO : org.springframework.web.context.support.AnnotationConfigWebApplicationContext - Registering annotated classes: [class com.twittermarketingtool.configuration.SpringSocialConfig,class com.twittermarketingtool.configuration.AppConfig,class com.twittermarketingtool.configuration.HibernateConfig]
WARN : org.springframework.context.annotation.ConfigurationClassEnhancer - #Bean method AppConfig.propertyPlaceHolderConfigurer is non-static and returns an object assignable to Spring's BeanFactoryPostProcessor interface. This will result in a failure to process annotations such as #Autowired, #Resource and #PostConstruct within the method's declaring #Configuration class. Add the 'static' modifier to this method to avoid these container lifecycle issues; see #Bean javadoc for complete details.
INFO : org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor - JSR-330 'javax.inject.Inject' annotation found and supported for autowiring
WARN : org.hibernate.dialect.Oracle9Dialect - HHH000063: The Oracle9Dialect dialect has been deprecated; use either Oracle9iDialect or Oracle10gDialect instead
INFO : org.springframework.security.web.DefaultSecurityFilterChain - Creating filter chain: org.springframework.security.web.util.matcher.AnyRequestMatcher#1, [org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter#7affc10f, org.springframework.security.web.context.SecurityContextPersistenceFilter#35bcf2b2, org.springframework.security.web.header.HeaderWriterFilter#5b2f3e74, org.springframework.security.web.csrf.CsrfFilter#165241a7, org.springframework.security.web.authentication.logout.LogoutFilter#5863f8aa, org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter#55794086, org.springframework.security.web.savedrequest.RequestCacheAwareFilter#30dfc977, org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter#6f9bdfe3, org.springframework.security.web.authentication.rememberme.RememberMeAuthenticationFilter#4abc2a35, org.springframework.security.web.authentication.AnonymousAuthenticationFilter#2cdbfedf, org.springframework.security.web.session.SessionManagementFilter#468410cd, org.springframework.security.web.access.ExceptionTranslationFilter#d813edb, org.springframework.security.web.access.intercept.FilterSecurityInterceptor#1000d825]
INFO : org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping - Mapped "{[/login],methods=[GET]}" onto public java.lang.String com.twittermarketingtool.controller.AppController.loginPage()
INFO : org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping - Mapped "{[/error],methods=[GET]}" onto public java.lang.String com.twittermarketingtool.controller.AppController.errorPage()
INFO : org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping - Mapped "{[/delete-user-{userName}],methods=[GET]}" onto public java.lang.String com.twittermarketingtool.controller.AppController.deleteUser(java.lang.String)
INFO : org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping - Mapped "{[/edit-user-{userName}],methods=[POST]}" onto public java.lang.String com.twittermarketingtool.controller.AppController.updateUser(com.twittermarketingtool.model.User,org.springframework.validation.BindingResult,org.springframework.ui.ModelMap,java.lang.String)
INFO : org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping - Mapped "{[/logout],methods=[GET]}" onto public java.lang.String com.twittermarketingtool.controller.AppController.logoutPage(javax.servlet.http.HttpServletRequest,javax.servlet.http.HttpServletResponse)
INFO : org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping - Mapped "{[/signup],methods=[GET]}" onto public java.lang.String com.twittermarketingtool.controller.AppController.newUser(org.springframework.ui.ModelMap)
INFO : org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping - Mapped "{[/ || /home],methods=[GET]}" onto public java.lang.String com.twittermarketingtool.controller.AppController.homePage()
INFO : org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping - Mapped "{[/signup],methods=[POST]}" onto public java.lang.String com.twittermarketingtool.controller.AppController.saveUser(com.twittermarketingtool.model.User,org.springframework.validation.BindingResult,org.springframework.ui.ModelMap)
INFO : org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping - Mapped "{[/edit-user-{userName}],methods=[GET]}" onto public java.lang.String com.twittermarketingtool.controller.AppController.editUser(java.lang.String,org.springframework.ui.ModelMap)
INFO : org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping - Mapped "{[/dashboard],methods=[GET]}" onto public java.lang.String com.twittermarketingtool.controller.AppController.profilePage(org.springframework.ui.ModelMap)
INFO : org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping - Mapped "{[/Access_Denied],methods=[GET]}" onto public java.lang.String com.twittermarketingtool.controller.AppController.accessDeniedPage(org.springframework.ui.ModelMap)
INFO : org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping - Mapped "{[/add_t_accounts/connect/twitter],methods=[GET]}" onto public java.lang.String com.twittermarketingtool.controller.TwitterIntegraionController.helloTwitter(org.springframework.ui.Model)
INFO : org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping - Mapped "{[/add_t_accounts],methods=[GET]}" onto public java.lang.String com.twittermarketingtool.controller.TwitterIntegraionController.addTwitterAccountsPage(org.springframework.ui.ModelMap)
INFO : org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping - Mapped "{[/twitter],methods=[GET]}" onto public java.lang.String com.twittermarketingtool.controller.TwitterProfileController.home(java.security.Principal,org.springframework.ui.Model)
INFO : org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping - Mapped "{[/connect/{providerId}],methods=[POST]}" onto public org.springframework.web.servlet.view.RedirectView org.springframework.social.connect.web.ConnectController.connect(java.lang.String,org.springframework.web.context.request.NativeWebRequest)
INFO : org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping - Mapped "{[/connect/{providerId}],methods=[DELETE]}" onto public org.springframework.web.servlet.view.RedirectView org.springframework.social.connect.web.ConnectController.removeConnections(java.lang.String,org.springframework.web.context.request.NativeWebRequest)
INFO : org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping - Mapped "{[/connect/{providerId}/{providerUserId}],methods=[DELETE]}" onto public org.springframework.web.servlet.view.RedirectView org.springframework.social.connect.web.ConnectController.removeConnection(java.lang.String,java.lang.String,org.springframework.web.context.request.NativeWebRequest)
INFO : org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping - Mapped "{[/connect/{providerId}],methods=[GET],params=[oauth_token]}" onto public org.springframework.web.servlet.view.RedirectView org.springframework.social.connect.web.ConnectController.oauth1Callback(java.lang.String,org.springframework.web.context.request.NativeWebRequest)
INFO : org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping - Mapped "{[/connect/{providerId}],methods=[GET],params=[code]}" onto public org.springframework.web.servlet.view.RedirectView org.springframework.social.connect.web.ConnectController.oauth2Callback(java.lang.String,org.springframework.web.context.request.NativeWebRequest)
INFO : org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping - Mapped "{[/connect/{providerId}],methods=[GET],params=[error]}" onto public org.springframework.web.servlet.view.RedirectView org.springframework.social.connect.web.ConnectController.oauth2ErrorCallback(java.lang.String,java.lang.String,java.lang.String,java.lang.String,org.springframework.web.context.request.NativeWebRequest)
INFO : org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping - Mapped "{[/connect/{providerId}],methods=[GET]}" onto public java.lang.String org.springframework.social.connect.web.ConnectController.connectionStatus(java.lang.String,org.springframework.web.context.request.NativeWebRequest,org.springframework.ui.Model)
INFO : org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping - Mapped "{[/connect],methods=[GET]}" onto public java.lang.String org.springframework.social.connect.web.ConnectController.connectionStatus(org.springframework.web.context.request.NativeWebRequest,org.springframework.ui.Model)
INFO : org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter - Looking for #ControllerAdvice: Root WebApplicationContext: startup date [Thu Nov 24 16:11:21 IST 2016]; root of context hierarchy
INFO : org.springframework.web.servlet.handler.SimpleUrlHandlerMapping - Mapped URL path [/static/**] onto handler of type [class org.springframework.web.servlet.resource.ResourceHttpRequestHandler]
INFO : org.springframework.web.servlet.handler.SimpleUrlHandlerMapping - Mapped URL path [/**] onto handler of type [class org.springframework.web.servlet.resource.DefaultServletHttpRequestHandler]
INFO : org.springframework.web.context.ContextLoader - Root WebApplicationContext: initialization completed in 9448 ms
Nov 24, 2016 4:11:31 PM org.apache.catalina.core.ApplicationContext log
INFO: Initializing Spring FrameworkServlet 'dispatcher'
INFO : org.springframework.web.servlet.DispatcherServlet - FrameworkServlet 'dispatcher': initialization started
INFO : org.springframework.web.context.support.AnnotationConfigWebApplicationContext - Refreshing WebApplicationContext for namespace 'dispatcher-servlet': startup date [Thu Nov 24 16:11:31 IST 2016]; parent: Root WebApplicationContext
INFO : org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor - JSR-330 'javax.inject.Inject' annotation found and supported for autowiring
INFO : org.springframework.web.servlet.DispatcherServlet - FrameworkServlet 'dispatcher': initialization completed in 95 ms
ERROR: org.springframework.social.support.LoggingErrorHandler - Response body: {"errors":[{"code":32,"message":"Could not authenticate you."}]}

Resources