I'm trying to get a Spring project to work with a simple rest service and a repository which fetches data from a MongoDB database. At this moment two separate things are working:
I can run this simple REST example: https://spring.io/guides/gs/rest-service/
I can connect to the MongoDB instance and fetch data
This both in separate projects.
I don't see, however, how I can bring these two together properly. At this moment I've tried the following based on several other tutorials and references (for example https://spring.io/guides/gs/accessing-mongodb-data-rest/). We now have 2 configs but when we deploy and try to go to rest url we just get 404's. it's not clear to me if the mapping is alright, I also don't see how the mapping is done in the first simple REST example.
Rest Controller:
#RestController
public class UserController {
#Autowired
private UserRepository userRepository;
#RequestMapping(value = "/users/{emailaddress}", method = RequestMethod.GET)
#ResponseBody
public User getUser(#PathVariable("emailaddress") String email) {
User user = userRepository.findByEmailAddress(email);
return user;
}
}
The Application class (as done in the tutorials):
#Configuration
#ComponentScan
#EnableAutoConfiguration
#Import(MongoConfig.class)
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
The MongoConfig class (which we assume is about right but not 100% sure):
#Configuration
public class MongoConfig extends AbstractMongoConfiguration {
#Override
protected String getDatabaseName() {
return "<dbname>";
}
#Override
public Mongo mongo() throws Exception {
MongoCredential mongoCredential = MongoCredential.createPlainCredential("<username>", "<dbname>", "<pswd>".toCharArray());
return new MongoClient(new ServerAddress("<dbaddress>", <port>), Arrays.asList(mongoCredential));
}
}
I really hope someone can shed some light on how to this best, we don't need a Spring (MVC) front-end, just a REST service which will get data from our MongoDB.
Thanks in advance.
I too had this problem, I still get 404 error while running through eclipse tomcat, but I deployed the war in the tomcat webapps and ran through the server which worked for me.
Related
I am trying to use a shared cache in a spring boot clustered app.
It seems that everything is working but when i tried to retrieve cached values from a second
instance of the app, it don't get it from cached values.
Seems like every app is working with his own cache and not sharing it.
I followed the guideline found here to setup a simple environment https://hazelcast.com/blog/spring-boot/
My code:
Controller.java
#Controller
#RequestMapping("/public/testcache")
public class TestCacheController {
#Autowired
BookService bookService;
#GetMapping("/get/{isbn}")
#ResponseBody
public String getBookNameByIsbn(#PathVariable("isbn") String isbn) {
return bookService.getBookNameByIsbn(isbn);
}
#GetMapping("/clear/cache")
#ResponseBody
public String clearCache() {
bookService.deleteCache();
return "done";
}
}
BookService.java
#Service
public class BookService {
#Cacheable("books")
public String getBookNameByIsbn(String isbn) {
return findBookInSlowSource(isbn);
}
private String findBookInSlowSource(String isbn) {
// some long processing
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
return "Sample Book "+isbn;
}
#CacheEvict(value = {"books"}, allEntries = true)
public void deleteCache() {}
}
# hazelcast.yaml
hazelcast:
network:
join:
multicast:
enabled: true
When i start the applications I always get the right output:
Members {size:2, ver:2} [
Member [192.168.178.107]:5702 - d53f2c3f-d66f-4ba3-bf8d-88d4935bde4e
Member [192.168.178.107]:5701 - 69860793-c420-48d3-990c-d0c30a3a92d6 this
]
I tried:
running two Spring Boot apps on different ports
running two tomcat on different ports
replace the yaml configuration with java configuration
Java Based Configuration
#Configuration
#EnableCaching
public class CacheConfigurator {
#Bean
public Config config() {
Config config=new Config();
config.getNetworkConfig().getJoin().getMulticastConfig().setEnabled(true);
return config;
}
}
Every time I get the same result, every app seems to cache on his own.
Additional information:
I tried to use management center https://hazelcast.com/product-features/management-center/ and i can connect to cluster member, but i never see any value under "Map"
I am wondering if the instances of hazelcast are launched but not used by spring boot that instead uses his own simple cache
My application.properties is empty
Spring boot version 2.4.4
Maybe each of your Spring Boot applications actually created two separate Hazelcast instances and it uses not clustered one for caching.
Please try to follow these guides:
Hazelcast Guides: Getting Started with Hazelcast using Spring Boot, it
Hazelcast Guides: Caching with Spring Boot and Hazelcast
I have a library-module written using Spring Boot 1.5.21.
The library has a #Service with some methods annotated with #PreAutorize allowing only users with ADMIN authority to perform some actions, for example a delete.
Then I have a Spring Boot Application that uses that library. If I run the app and manually test it, it works. Only ADMINs can delete. I'd like to write test for it.
I was thinking in writing separate test for module and for the main app. In my module I can successfully unit test the operations. But I'm having troubles testing the #PreAuthotize, because the security context does not exist in the module, but in the main app. Is there a way to test that annotation in the module, and not in the main app?
The relevant code of my library:
#Service
public class MyService {
#PreAuthorize("hasAuthority('ADMIN')")
public void delete (long id){
.....
}
}
#RunWith(SpringRunner.class)
public class MyServiceTest {
private MyService service;
#Test
#WithAnonymousUser
public void deleteShouldFailIfAnonymous() {
... Verify exception thrown
}
#Test
#WithMockUser(authorities = 'USER')
public void deleteShouldFailIfNotAdmin() {
... Verify exception thrown
}
#Test
#WithMockUser(authorities = 'ADMIN')
public void deleteShouldPass() {
... Should pass
}
}
I've trying adding #EnableGlobalMethodSecurity(prePostEnabled = true) but with no luck. And as said, the SecurityConfiguration is loaded in the main app, it does not exist in the library-module.
Can I test the #PreAuthorize in the module or should I move it to the main app? I'd like to have it i the module if possible. Or maybe I can create a Context only for testing, but don't know how to do it.
Aspect-oriented features like #PreAuthorize are implemented as advice. Usually, this means that Spring will create a decorator interface that intercepts the method call, performs the advice (in this case, checking the condition and throwing an exception if it fails), and then sends the call on to the service object.
When you use new MyService, you're creating a bare object without the wrappers that implement the advice, so you won't see security, validation, caching, etc., applied. To see the behavior you want, you need to make your test bean #Autowired using the Spring test support.
You can use the MockMvc to test. This will help with module testing incase of integration testing.
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration
#WebAppConfiguration
public class SecurityTests {
#Autowired
private WebApplicationContext context;
private MockMvc mvc;
#Before
public void setup() {
mvc = MockMvcBuilders.webAppContextSetup(context).apply(springSecurity()).build();
}
#WithMockUser(roles="ADMIN")
#Test
public void withMockUser() {
mvc.perform(get("......"))
}
}
I am new to Spring / Spring Boot.
In my Spring Boot Application, I have a JAR file which has a Controller class and corresponding Service Interface (not class). I have implemented the Service interface and created a Service class with some logic. Now I want to access the APIs (/v1/getDetails) present in Controller class of JAR file.
Can we access the REST APIs present in Controller class of JAR file? If so then please guide me.
PS: I have tried to search on internet but didn't get a clear answer.
Controller class in Jar:
#RestController("/v1")
public class BasicRestController {
#Autowired
BasicServiceInterface basicService;
#GetMapping("/supportedDeviceTypes")
public NameValuePair<?> getSupportedDeviceTypes() {
return basicService.getSupportedDeviceTypes();
}
}
Spring Boot Main Class:
#SpringBootApplication
public class XXXProjectApplication{
public static void main(String[] args) {
SpringApplication.run(XXXProjectApplication.class, args);
}
}
Configuration Class:
#Configuration
public class CommonControllerConfig {
#Bean
public BasicRestController basicRestController() {
return new BasicRestController();
}
}
Accessing http://localhost:8080/v1/supportedDeviceTypes but getting - 'This application has no explicit mapping..' in browser.
But I have printed the loaded beans in Application Context and could see BasicRestController bean is loaded while starting the app.
Try removing following bean from CommonControllerConfig
#Bean
public BasicRestController basicRestController() {
return new BasicRestController();
}
And instead add #ComponentScan(basePackages = "your.controller.package")
Also, as JB Nizet mentioned, it should be #RestController #RequestMapping("/v1") in BasicRestController.
hey guys i have a problem in my java spring boot application
i've built a simple application and connected it with a database
but when i try to make a POST or GET on the data base my program access the database and do any thing i did but show an error
org.thymeleaf.exceptions.TemplateInputException: Error resolving template "Students", template might not exist or might not be accessible by any of the configured Template Resolvers
when i make GET i check the Iterable list and it's already get the data from database
but doesn't show the data on the localhost
it's give me that exception
is there any solution for that ?
this is my code in controller
#Path("Students")
#Controller
public class studentsController {
#AutoWired
StudentServices st;
#RequestMapping(method = RequestMethod.GET)
public Iterable<Students> getAllStudents() {
Iterable<Students> list = st.getAllStudents();
return list
}
With #Controller you are defining a Model-View-Controller (MVC) endpoint for returning your view templates. So with Iterable<Students> Spring is looking for a Students template in your src/main/resources/templates folder because it is interpreted as a View name.
If you want to create a REST endpoint which returns a list of Student objects you should use #RestController at your class which adds the Spring annotation #RequestBody automatically.
Furthermore #Path("XYZ") should be replaced with #RequestMapping("XYZ") in Spring and #AutoWired with #Autowired.
An working example could look like the following:
#RequestMapping("/students")
#RestController
public class StudentsController {
#Autowired
StudentServices st;
#RequestMapping(value="/", method = RequestMethod.GET)
public Iterable<Students> getAllStudents() {
Iterable<Students> list = st.getAllStudents();
return list
}
I want to make a simple java application and I want to use CRUDREPOSITORY and my own repository. I have this:
#RestController
#Transactional
#ExposesResourceFor(Person.class)
#RequestMapping("/prueba")
public class PersonController {
#RequestMapping(value="/prueba", method=RequestMethod.GET)
public String person(#RequestParam(value="id", defaultValue="1") int id) {
return "hola"+id;
}
}
this:
#RepositoryRestResource
public interface IClientRepository extends CrudRepository<Client, Long> {
}
The problem is that the CRUD works well, but I canĀ“t call my localhost:8080/prueba/prueba because it gives a 404 error. I have try all and I cant access it, please help me!!
By default, Spring Data REST serves up REST resources at the root URI, "/". There are multiple ways to change the base path.
With Spring Boot 1.2+, add below to application.properties:
spring.data.rest.basePath=/api
In your case:
spring.data.rest.basePath=/prueba/prueba
, assuming there is no override for server.contextPath in application.properties
Reference:
http://docs.spring.io/spring-data/rest/docs/current/reference/html/