#RestController
public class MainController {
#Autowired
private UserRepository userRepository;
#RequestMapping(path="/home")
public String homes(){
return "index.jsp";
}
}
when I am using #controller it is returning JSPs but when I change to #Restcontroller,
localhost:8080/home returns a page with the string "index.jsp".
Related
I'm trying to write tests for my spring controller and having a problem. when().thenReturn() doesn't work. Here is the code:
Controller:
#Controller
#CrossOrigin
#RequestMapping("/api")
public class LoginController{
private final ApplicationConfig applicationcfg;
public LoginController (ApplicationConfig applicationcfg){
this.applicationcfg = applicationcfg;
}
....
#GetMapping(value = "/token")
public ResponseEntity<?>login(#RequestParam String ticket){
//got a null in applicationcfg.getKey() when run test
ResponseTicket resTicket = ResponseTicket.deserialize(ticket, applicationcfg.getKey());
return RestResponse.success(resTicket.getUserId());
}
}
ApplicationConfig:
#Configuration
#Getter
public class ApplicationConfig{
#Value("${auth_key}")
private String key;
}
And the test code:
#SpringBootTest
#ExtendWith(SpringExtension.class)
class LoginControllerTest{
private MockMvc mvc;
#InjectMocks
LoginController loginController;
#Mock
ApplicationConfig applicationCfg;
#BeforeEach
void setUp(){
MockitoAnnotations.openMocks(this);
mvc = MockMvcBuilders.standaloneSetup(loginController).build();
}
#Test
void test(){
when(applicationCfg.getKey()).thenReturn("1234ABCD");
MockHttpServletRequestBuilder request = MockMvcRequestBuilders.get("/api/token").param("ticket","1234567");
mvc.perform(request).andExpect(MockMvcResultMatchers.status().isOk());
}
}
Why when().thenReturn() doesn't work?
I have 2 rest controllers which look the same:
File 1:
#RestController
#RequestMapping("/api/v1/foo")
#RequiredArgsConstructor
public class FooAPI {
private final ConfigService<Foo> service;
#GetMapping
(...)
File 2:
#RestController
#RequestMapping("/api/v1/bar")
#RequiredArgsConstructor
public class BarAPI {
private final ConfigService<Bar> service;
#GetMapping
(...)
Everything is the same, except the private final ConfigService<(Foo|Bar)> service;.
Is it possible to generalize a restcontroller class?
You can create abstract class that you can inherit from.
So you get something like:
Abstract class:
public abstract class AbstractAPI {
private final ConfigService<?> service;
public AbstractAPI(ConfigService<?> service){
this.service = service;
}
#GetMapping
(...)
File 1:
#RestController
#RequestMapping("/api/v1/foo")
public class FooAPI extends AbstractAPI {
public FooAPI (ConfigService<?> service) {
super(service);
}
}
File 2:
#RestController
#RequestMapping("/api/v1/bar")
public class BarAPI extends AbstractAPI {
public BarAPI (ConfigService<?> service) {
super(service);
}
}
#Service
public class UserService {
private String name;
//fields omitted
//#Cacheable(value = "user", key = "#name") //once added, the name will be null.
public User getUser(String name) {
}
}
#Service
class UserServiceBuilder(){
public UserService build(ConfigBean config){
UserService s = new UserServcie()
s.name = config.xxxx
//other config omitted
return s;
}
}
#Configuration
class AppConfig{
#Bean
public UserService UserService(UserServiceBuilder builder, ConfigBean configBean) {
return builder.load(configBean);
}
}
class UserCtrl {
#Autowired
private UserService UserService; // get null when the #Cachable
}
UserService is created by the UserServiceBuilder which will read a log of properties from the config file.
Then the UserService will be injected to UserCtrl, it works at first.
However once I add the #Cachable to one method of UserService, all the fileds of the injected UserService will be null.
It seems like that spring will create a proxy of UserService when using cache, and the proxy object does not have the fileds.
How to fix that?
Yes, you are right it's because of the proxy. You must add getters in the UserService and use this getters if you want take the fields of the UserService outside.
#Service
public class UserService {
private String name;
//fields omitted
//#Cacheable(value = "user", key = "#name") //once added, the name will be null.
public User getUser(String name) {
}
//ADD THIS:
public String getName() {
return this.name;
}
}
But if you add output inside UserService method:
public User getUser(String name) {
System.out.println("PING " + this.name);
...
}
you will see that this.name inside object is not null.
P.S. and I think that you can remove #Service annotation from UserService. Because you have #Service and #Bean registration of UserService. It's confusing.
I have a few classes in the JPA Base made with the use of SpringData and SpringBoot. I would like to create a controller which shows the rest out of a few classes and not only one. Sadly, I can't find any examples.
This is my controller:
#RestController
#RequestMapping("/user")
public class UserController {
private final UserRepository userRepository;
#Autowired
public UserController(UserRepository userRepository) {
this.userRepository = userRepository;
}
#RequestMapping(method = RequestMethod.POST)//add
public void addUser(#RequestBody User user) {
userRepository.save(user);
}
#RequestMapping(method = RequestMethod.GET)
public List<User> getUser(){
return userRepository.findAll();
}
}
I have the following controller:
#RepositoryRestController
public class TestController {
#RequestMapping(value = "/testables", method = RequestMethod.GET)
public String get(){
return "testin it";
}
}
And it is not picked up by Spring. I get 404 when I hit /apiroot/testables address. If I change it to be #RestController and add the api root to request mapping value, then it works. Also, if I change the mapping to point to "/orders/testables", it works as #RepositoryRestController. I also have the following controller in the same package which works fine:
#RepositoryRestController
public class SendEmailController {
#Autowired
private MessageSource messageSource;
#Autowired
private JavaMailSender javaMailSender;
#Autowired
private OrderRepository orderRepository;
#RequestMapping(value = "/orders/{id}/sendOrderEmailToSupplier")
public void sendOrderEmailToSupplier(#PathVariable("id") Long id, WebRequest request) throws MessagingException {...
#RepositoryRestController deal with basePath only for resources which it manage. In other cases the path should not contain the "base".
If you want to build custom operations underneath basePath, you can use #BasePathAwareController.