Spring Boot and plain html - html

Does anyone tuned spring boot to use as a view plain html without thymeleaf?
Here is my configuration:
#SpringBootApplication
#EnableAutoConfiguration
#ComponentScan
#Configuration
#EnableWebMvc
public class WebUi extends WebMvcConfigurerAdapter {
#Bean
public InternalResourceViewResolver getInternalResourceViewResolver() {
InternalResourceViewResolver resolver = new InternalResourceViewResolver();
resolver.setPrefix("/WEB-INF/");
resolver.setSuffix(".html");
return resolver;
}
#Override
public void addViewControllers(ViewControllerRegistry registry) {
registry.addViewController("/login").setViewName("login");
}
//
// #Override
// public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
// configurer.enable();
// }
public static void main(String[] args) {
SpringApplication.run(WebUi.class, args);
}
}
I've tried with enabling DefaultServletHandler and without. The html file placed in src/main/resources/WEB-INF/login.html and assembled. I see it in the classpath in debug. But request to http://localhost:8080/login returns 404.
What I'm doing wrong?

Remove all annotations only leave #SpringBootApplication.
Remove your InternalResourceViewResolver and simply add the following to the application.properties.
spring.view.prefix=/WEB-INF/
spring.view.suffix=.html
Your current application class interferes with the Spring Boot auto configuration due to the #EnableWebMvc. Next #SpringBootApplication already implies #Configuration, #EnableAutoConfiguration and #ComponentScan no need to add them again.
When adding the spring.view.* properties Spring Boot already configures a InternalResourceViewResolver for you.
Basic advice here is work with the framework not around/against the framework.

Related

How to rollback Rabbit-mq message after Junit test?

When you test your code, you send a message to rabbit-mq. How do you get the message back when the test is over?
public interface RabbitProducer {
String OUTPUT = "rabbitmq_producer_channel";
#Output(OUTPUT)
MessageChannel output();
}
public class SysGroupServiceImpl {
#Autowired
private RabbitProducer rabbitProducer;
#Override
public Result remove(Collection<? extends Serializable> idList) {
rabbitProducer.output().send(MessageBuilder.withPayload(idList)
.setHeader("x-delay", 5000)
.setHeader("MessageType", "GroupBatchDelete").build());
return Result.booleanResult(true);
}
}
#SpringBootTest
#Transactional
#Rollback
public class SysGroupServiceTest {
#Autowired
private SysGroupService sysGroupService;
#Test
void removeTest(){
sysGroupService.remove(Stream.of("1").collect(Collectors.toList()));
}
}
I use Spring Cloud Stream to be compatible with RabbitMQ, and all the relevant code is there.Is there a way to mock this out?I tried the following scheme, but due to X-dealy, I got this error:No exchange type x-delayed-message
<dependency>
<groupId>com.github.fridujo</groupId>
<artifactId>rabbitmq-mock</artifactId>
</dependency>
#Component
public class RabbitMqMock {
#Bean
public ConnectionFactory connectionFactory() {
return new CachingConnectionFactory(MockConnectionFactoryFactory.build());
}
}
I know little about mocks. Can mocks create an X-delay exchange?

Spring Boot UserRedirectRequiredException- A redirect is required to get the users approval

I am learning OAUTH2 implementation
When i hit my client end http://localhost:8082/ui - REST end point for UI which will take me to the secure URI http://localhost:8082/secure after logging into the auth server http://localhost:8081/auth/login.
But it fails at http://localhost:8082/ui/login and give me error as
org.springframework.security.oauth2.client.resource.UserRedirectRequiredException: A redirect is required to get the users approval
My client configuration is
OauthConfig.java
#EnableOAuth2Sso
#Configuration
public class OauthConfig extends WebSecurityConfigurerAdapter {
#Override
protected void configure(HttpSecurity http) throws Exception {
// TODO Auto-generated method stub
http.antMatcher("/**").
authorizeRequests().antMatchers("/","/login**").permitAll().anyRequest().authenticated();
/*http
.authorizeRequests().anyRequest().authenticated();*/
}
}
and webconfig.java
#SuppressWarnings("deprecation")
#EnableWebMvc
#Configuration
public class WebConfig extends WebMvcConfigurerAdapter {
#Override
public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
// TODO Auto-generated method stub
configurer.enable();
}
#Override
public void addViewControllers(ViewControllerRegistry registry) {
// TODO Auto-generated method stub
super.addViewControllers(registry);
registry.addViewController("/").setViewName("forward:/index");
registry.addViewController("/index");
registry.addViewController("/secure");
}
#Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
// TODO Auto-generated method stub
registry.addResourceHandler("/resources/**").addResourceLocations("/resources/");
}
#Bean
public static PropertySourcesPlaceholderConfigurer placeHolderConfigurer()
{
return new PropertySourcesPlaceholderConfigurer();
}
#Bean
public RequestContextListener contextlist()
{
return new RequestContextListener();
}
#Bean
public static PropertySourcesPlaceholderConfigurer placeholderConfigurer() {
return new PropertySourcesPlaceholderConfigurer();
}
}
and my application.yml is
server:
port: 8082
servlet:
context-path: /ui
session:
cookieName: UISESSION
spring:
thymeleaf:
cache: false
oauth2:
client:
client-id: ClientId
clientSecret: secret
accessTokenUri: http://localhost:8081/auth/oauth/token
userAuthorizationUri: http://localhost:8081/auth/oauth/authorize
clientAuthenticationScheme: form
resource:
userInfoUri: http://localhost:8081/auth/rest/hello/principal
preferTokenInfo: false
Do i need to write custom oauth2ClientContextFilter for this? i already have added spring-security-oauth2 to the pom.xml. Any help would be really appreciated.
I had a similar experience and by exchanging #EnableOAuth2Sso by #EnableOAuth2Client it was solved.
It seems that the #EnableOAuth2Sso annotation adds an additional Security Chain Filter OAuth2ClientAuthenticationProcessingFilter to the springSecurityFilterChain and this throws the UserRedirectRequiredException.
Update SecurityContextHolder
SecurityContextHolder.setStrategyName(SecurityContextHolder.MODE_INHERITABLETHREADLOCAL);

Usage of #Scheduled in spring

I have a component class
#Component
public class Scheduler
{
#Scheduled(fixedRate = 5000 )
public void test()
{
System.out.println("Hi");
}
}
But "Hi" is not being printed every 5 seconds. Why?
My Confuration class is
#ComponentScan( excludeFilters = { #ComponentScan.Filter( type = FilterType.ASSIGNABLE_TYPE ) } )
#EnableScheduling
#SpringBootApplication
public class Application
{
public static void main( final String[] args )
{
LOG.debug("Booting Spring Application ...... ");
SpringApplication.run(Application.class, args);
}
}
In your main application class add #EnableScheduling and also see that package in which Scheduler is kept is scanned by using #ComponentScan if all packages are not scanned by you.
#EnableScheduling
#SpringBootApplication
#EnableAutoConfiguration
#ComponentScan(basePackages = "springboot.service,springboot.dao,springboot.rest,springboot.schedule,springboot.controller")
public class StartUpController {
public static void main(String[] args) throws Exception {
SpringApplication.run(StartUpController.class, args);
}
}
Is your Scheduler class in the same or a sub-package of your application class? If not, you have to add the base-packages attribute to the #ComponentScan annotation, so that the Scheduler component will be found.

How to disable jersey filters for unit tests only (using spring-boot)

I have a spring-boot application with Jersey as the REST engine.
I am using Jersey filters for authenticating each request.
The question is what is the appropriate way to disable these filters or provide mock filters during unit tests of the REST controllers (with JUnit)?
Here is what I have:
Spring boot application:
#PropertySource("classpath:security-api.properties")
#SpringBootApplication
public class MyApplication {
public static void main(String[] args) {
SpringApplication.run(MyApplication.class, args);
}
}
Jersey Configuration file:
#Configuration
#ApplicationPath("/some/path")
public class MyJerseyConfiguration extends ResourceConfig {
public AnalyzerJerseyConfiguration() {
packages(BaseController.class.getPackage().getName());
register(AuthorizationRequestFilter.class);
register(AuthorizationResponseFilter.class);
}
}
Probably your best bet is to use Spring Profiles. You can mark the ResourceConfig in your post as, as a "production" configuration, while for tests, create a new ResourceConfig with a "test" profile. Then in your tests just set the active profile to "test", and in production, set the active profile to "production"
#Profile("production")
#Configuration
#ApplicationPath("/some/path")
public class MyJerseyConfiguration extends ResourceConfig {
public AnalyzerJerseyConfiguration() {
packages(BaseController.class.getPackage().getName());
register(AuthorizationRequestFilter.class);
register(AuthorizationResponseFilter.class);
}
}
#Profile("test")
#Configuration
#ApplicationPath("/some/path")
public class TestConfiguration extends ResourceConfig {
public AnalyzerJerseyConfiguration() {
packages(BaseController.class.getPackage().getName());
register(TestRequestFilter.class);
register(TestResponseFilter.class);
}
}
#ActiveProfiles("test")
#RunWith(SpringJUnit4ClassRunner.class)
public class TestClass {}
You can also set the active profiles in your property configuration files (as mentioned in the above link).
If you want different configurations for different tests, instead of creating a bunch of ResourceConfig subclasses, it might just make more sense to create different spring configurations. You can just create #Bean methods for different configurations.
#Profile("test")
#Configuration
public class TestOneConfig {
#Bean
public ResourceConfig resourceConfig() {
return new ResourceConfig()
.register(Something.class);
}
}
#Profile("test")
#Configuration
public class TestTwoConfig {
#Bean
public ResourceConfig resourceConfig() {
return new ResourceConfig()
.register(DifferentSomething.class);
}
}
Whichever one you want to use, just add that to the test configuration.
#ActiveProfiles("test")
#SpringApplicationConfiguration(classs={MainApp.class, TestOneConfig.class})
public class TheTest {}
With Spring Boot 1.4 (Not yet released), they introduce a ResourceConfigCustomizer. This might make it a little cleaner, without the need to create a "test" ResourceConfig, you might be able to do something like
#Component
public class TestCustomizer implements ResourceConfigCustomizer {
#Override
public void customize(ResourceConfig config) {
config.getClasses().remove(AuthorizationRequestFilter.class);
config.register(TestRequestFilter.class);
}
}
and register this in a test configuration.

Using HttpMessageConverter causes HTTP 406

After extensive investigations, I wanted to share the problem and the resolution.
Problem
I have a RestController that works well, as long as I'm in charge of converting the JSON message. The moment I try to use an HttpMessageConverter to make the conversion more elegant, the client will start receiving HTTP 406.
So this works:
#RequestMapping(value = "/objects", method = RequestMethod.GET)
public Map<String, Object>[] getObjects(#RequestBody Object jsonQuery) {
MyQuery query = new MyConverter().convert(jsonQuery);
// do something with query
}
But, when I configure the converter, like this:
#Configuration
#EnableWebMvc
#ComponentScan
public class WebConfiguration extends WebMvcConfigurerAdapter {
#Override
public void configureMessageConverters(List<HttpMessageConverter<?>> httpMessageConverters) {
httpMessageConverters.add(new QueryMessageConverter(new MediaType("application", "json")));
}
}
This causes HTTP 406:
#RequestMapping(value = "/objects", method = RequestMethod.GET)
public Map<String, Object>[] getObjects(#RequestBody Query Query) {
// do something with query
}
My pom.xml only refers spring-boot, and doesn't mention jackson at all.
Solution
See below
The solution is really very simple, and it is to register the jackson handler explicitly:
#Configuration
#EnableWebMvc
#ComponentScan
public class WebConfiguration extends WebMvcConfigurerAdapter {
#Override
public void configureMessageConverters(List<HttpMessageConverter<?>> httpMessageConverters) {
httpMessageConverters.add(new QueryMessageConverter(new MediaType("application", "json")));
httpMessageConverters.add(new MappingJackson2HttpMessageConverter());
}
}