spring boot with JAX-RS resources - jax-rs

How do I configure JAX-RS resources with spring boot to be available with the embedded tomcat container?
Below is the JAX-RS resource I have (Groovy):
#Component
#Path('files')
#CompileStatic
class MyResource {
#Autowired
FileRepository repository
#GET
#Path('{id}')
#Produces(value = MediaType.APPLICATION_JSON)
Response getFileDetails(#PathParam("id") String id) {
println "getFileDetails called with $id"
return Response.ok().build()
}
}
When I try http GET with localhost:8080/files/123 I get 404 error. What am I missing?
I do not see errors during tomcat startup.

I had to specify jersey SpringServlet in SpringApplication.run. That fixed it.
#Configuration
#EnableAutoConfiguration
#ComponentScan
class Application {
public static void main(String[] args) {
ApplicationContext context = SpringApplication.run(
[SpringServlet.class,
"classpath:/META-INF/bootstrap.xml"] as Object [], args)
}
}

Related

Quarkus 2.5: #Inject inside JAX-RS Application subclass not working anymore

After upgrading Quarkus from 1.6.1.Final to 2.5.Final the following #Inject fails inside javax.ws.rs.core.Application subclass:
#ApplicationScoped
public class MyBean {
public String foo() {
retun "bar";
}
}
#ApplicationPath("/")
public class MyApplication extends Application {
#Inject
MyBean myBean;
#Override
public Set<Class<?>> getClasses() {
myBean.foo(); // Causes NPE on Quarkus 2.5.Final, worked well with 1.6.1.Final
}
}
I tried with CDI.current().select(MyBean.class).get() but got Unable to locate CDIProvider.
Any other workaround I can try? Thanks.
#Inject in JAX-RS Application classes has been since disallowed. I was able to solve my issue (registering resource classes by config) using #IfBuildProperty annotation.

How can I provide my custom OAuth2LoginAuthenticationProvider in spring boot

I am trying to setup OAuth2 login in spring boot, every thing is working good in my dev environment, however when I deploy it on production behind the Apache Http server using proxy configuration, authentication fails on Invalid Redirect URI check.
As suggested in some other post I already tried
1. use-forward-headers: true
2. Rewriting the request redirect URI
with no luck.
So I decided to hook my own custom OAuth2LoginAuthenticationProvider so that I can override this check.
public class SecurityConfig extends WebSecurityConfigurerAdapter{
#Value("${baseUrl}")
private String domainPath;
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.addFilterBefore(new MyCustomFilter(domainPath), OAuth2LoginAuthenticationFilter.class)
.authorizeRequests()
.antMatchers("/").permitAll()
.anyRequest().authenticated().and()
.logout().logoutSuccessUrl("/")
.and()
.oauth2Login().userInfoEndpoint().customUserType(CmmOAuth2User.class, "custom");
}
#Bean
public MyOAuth2AuthenticationProvider authenticationProvider() {
MyOAuth2AuthenticationProvider authProvider
= new MyOAuth2AuthenticationProvider();
return authProvider;
}
#Autowired
public void configureProviderManager(ProviderManager providerManager) {
providerManager.getProviders().add(0,authenticationProvider());
}
#Bean
public ProviderManager authenticationManager() {
List<AuthenticationProvider> authProviderList = new ArrayList<AuthenticationProvider>();
authProviderList.add(0,authenticationProvider());
ProviderManager providerManager = new ProviderManager(authProviderList);
return providerManager;
}
}
My custom MyOAuth2AuthenticationProvider is not being called.

Spring security authentication How to get rid of

Trying to do simple spring boot security test.
I can pass the test only with deprecated NoOpPasswordEncoder in
globalConfigure() method in SpringSecurityConfig.
it works fine, but is it possible get rid of deprecated NoOpPasswordEncoder?
#Configuration
#EnableWebSecurity
public class SpringSecurityConfig extends WebSecurityConfigurerAdapter {
#Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf().disable().authorizeRequests().anyRequest().fullyAuthenticated()
.antMatchers("/").permitAll()
.and()
.formLogin().defaultSuccessUrl("/", true)
.loginPage("/login").permitAll().and().logout().permitAll()
.and().httpBasic();
}
#SuppressWarnings("deprecated")
#Autowired
public void configureGlobal(AuthenticationManagerBuilder authBuilder) throws Exception{
authBuilder.inMemoryAuthentication()
.passwordEncoder(NoOpPasswordEncoder.getInstance())
.withUser("user").password("user").roles("USER")
.and()
.withUser("admin").password("admin").roles("USER", "ADMIN");
}
}
Testing spring security
#RunWith(SpringJUnit4ClassRunner.class)
#AutoConfigureMockMvc
#SpringBootTest
public class SpringSecurityConfigTest {
#Autowired
MockMvc mockMvc;
#Test
public void userIsAuthenticatedTest() throws Exception {
mockMvc.perform(formLogin().user("admin").password("admin"))
.andExpect(authenticated());
}
}
It depends what you want to do exactly. If you just want your test to pass and get rid of the deprecation you can remove the password encoder and add the {noop} prefix to the passwords in your configureGlobal method:
#Autowired
public void configureGlobal(AuthenticationManagerBuilder authBuilder) throws Exception {
authBuilder.inMemoryAuthentication()
.withUser("user").password("{noop}user").roles("USER")
.and()
.withUser("admin").password("{noop}admin").roles("USER", "ADMIN");
}
Spring Security 5 changed the default password encoder to Delegating Password Encoder which uses the prefix in curly braces to determine which password encoder to use, s. https://docs.spring.io/spring-security/site/docs/5.0.5.RELEASE/reference/htmlsingle/#pe-dpe-format
However, if you want to use this security config in production you should probably use a different encoder anyway.

Spring Data Rest base path

I have added Spring Data Rest (2.0) to an existing Spring MVC application by creating a Java config class that extends RepositoryRestMvcConfiguration, and adding #RestResource to the repositories.
Is it possible to change the base URL for the Rest API? E.g:
http://localhost:8080/rest/customers
instead of
http://localhost:8080/customers
I tried to override configureRepositoryRestConfiguration using setBaseURI, but it didn't seem to apply to all links in the response.
As of Spring Boot 1.2 you are able to set this property:
spring.data.rest.baseUri=api
Alternatively:
spring.data.rest.base-uri=api
(Spring Boot uses a relaxed binding system)
NOTE: I have found that if you have extended RepositoryRestMvcConfiguration with custom configuration, the property does not take effect. For more information see:
https://github.com/spring-projects/spring-boot/issues/2392
Once the next version of Spring Boot is released (after 1.2.1), the solution will be to extend RepositoryRestMvcBootConfiguration instead.
You can configure the RepositoryRestMvcConfiguration by overriding it in the following manner:
#Configuration
#Import(RepositoryRestMvcConfiguration.class)
public class RestDataConfig extends RepositoryRestMvcConfiguration {
#Override
protected void configureRepositoryRestConfiguration(RepositoryRestConfiguration config) {
super.configureRepositoryRestConfiguration(config);
try {
config.setBaseUri(new URI("/data"));
} catch (URISyntaxException e) {
e.printStackTrace();
}
}
}
I used spring boot 1.2.3.REALEASE
I tried spring.data.rest.baseUri=/api and spring.data.rest.basePath=/api but it not working.
After try and googling: server.servlet-path=/api worked for me.
Add to following line to application.properties(Spring boot version 2.2.0.M2)
spring.mvc.servlet.path=/rest
Hope this helps
I solved my problem by adding a second "AbstractAnnotationConfigDispatcherServletInitializer":
public class RestWebAppInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {
#Override
protected Class<?>[] getRootConfigClasses() {
return null;
}
#Override
protected Class<?>[] getServletConfigClasses() {
return new Class<?>[] { RepositoryRestMvcConfiguration.class };
}
#Override
protected String[] getServletMappings() {
return new String[] { "/rest/*" };
}
#Override
protected Filter[] getServletFilters() {
return null;
}
#Override
protected String getServletName() {
return "rest-exporter";
}
}
Look at official documentation how to change rest base uri
But I don't know why for me spring.data.rest.basePath=/api property is not working and I must wrote second solution:
#Configuration
class CustomRestMvcConfiguration {
#Bean
public RepositoryRestConfigurer repositoryRestConfigurer() {
return new RepositoryRestConfigurerAdapter() {
#Override
public void configureRepositoryRestConfiguration(RepositoryRestConfiguration config) {
config.setBasePath("/api");
}
};
}
}
See official documentation
https://docs.spring.io/spring-boot/docs/current/reference/html/common-application-properties.html
server.servlet-path=/ # Path of the main dispatcher servlet.
server.context-path=
you can include it on the configuration file.
See also Add context path to Spring Boot application
You set the property, e.g. in your YAML file:
spring.data.rest.base-path=/rest

EJB 3.1 : Singleton bean not getting injected inside another stateless bean though both beans are getting registered

Here is my bean that is trying to inject a singleton bean InformationService :
#Path("/information/{name}")
#Stateless (name="InformationResource")
public class InformationResource {
#EJB
private InformationService appService;
#GET
#Produces(MediaType.APPLICATION_XML)
public Information getInfo(#PathParam("name") String name){
return appService.getMap().get(name);
}
#PUT
#POST
#Consumes(MediaType.APPLICATION_XML)
public Information putInfo(#PathParam("name") String name, Information info){
return appService.getMap().put(name,info);
}
#DELETE
public void deleteInfo(#PathParam("name") String name){
appService.getMap().remove(name);
}
}
This is the InformationService class
#Singleton
public class InformationService {
private Map<String,Information> map;
#PostConstruct
public void init(){
map = new HashMap<String,Information>();
map.put("daud", new Information("B.Tech","Lucknow"));
map.put("anuragh", new Information("M.Sc","Delhi"));
}
public Map<String,Information> getMap(){
return map;
}
}
Its part of a very simple JAX-RS implementation and I am deploying as war in JBoss 6.1 Final. The problem is that InformationService throwing a NullPointerException when I make the proper get request. If I initialize appService explicitly, everything works fine. Why is #EJB annotation not working ?
Are you using Jersey as REST implementation? If so, EJB injection is not supported out of the box.
This link provides more information on this and also a solution.
Check that your #Singleton is javax.ejb.Singleton.
Any other exceptions before NPE ?