I am new to Spring and ROO and this Annotation/Aspect hell.
I have an Spring MVC Project created with Spring ROO.
I use mongo-db as my persistance layer.
I have an entity Report with the domain object, the service, the repository and the controller.
I added a custom controller wich workes so far.
I want to just access my stored reports with the ReportService.findAllReports(), but I'm not sure how to get access to this service.
Here is a link to my roo generated site http://sauberseite.cloudfoundry.com/
The main objective is to report adresses and then display all adresses in a google map, for which I have my custom controller and where I need to access the service layer
You can directly #Autowired it as follows.
#Controller
public class CustomController {
#Autowired
ReportService reportService; //this inject's your bean here.
List<Report> getReports() {
return reportService.findAllReports();
}
}
If you don't use annotation #Controller and defined your bean in xml, then you can inject ReportService as a property (just remove #Autowired annotation) and write a setter for it.
Related
I have a Spring 5 web application which does validations only on service level DTOs. That is to say, the incoming request is not validated in controller, but the DTO going into a service layer method is validated on that level. This is a requirement because this is how this is done on other applications and other people want to keep it like that for consistency.
I have tests that use Spring MockMvc to test the controller methods. I'd like to test the error response on validation errors but when I run my tests, bean validation is not done. It works fine when I build and deploy the app, though. Validation also works for tests if I put the validation annotations on the class representing the incoming request and add #Valid to the controller method argument corresponding to the request. It just doesn't work when its done on the service layer.
So my question is is this even supposed to work with MockMvc, that is to say, should validation occur normally when the controller calls the service method? Or is there some configuration I need to have in place for this to work during tests? I doubt it since validation works if I try adding it to controller level...
Here is my test class setup:
#ContextConfiguration(classes = {MyTestConfig.class})
#WebAppConfiguration
#RunWith(SpringJUnit4ClassRunner.class)
public class MyTest {
private MockMvc mvc;
#Autowired
private WebApplicationContext wac;
#Before
public void setup() throws Exception {
this.mvc = MockMvcBuilders.webAppContextSetup(this.wac).build();
}
The MyTestConfig class just has #EnableWebMvc annotation, base packages for scanning and some unrelated bean definitions.
My DTO has #NotNull annotation on a property, the service method has a #Validated annotation on the class and a #Valid annotation on the method parameter which is the DTO.
With these settings, when I make a request in a test to the controller endpoint using the MockMvc instance mvc above, validation does not occur on the service method.
So is this even supposed to work?
I would like to create a builder class (i.e. a class implementing the builder design pattern) in a Spring project.
The problem is that I need the builder to use some Spring services.
I obviously don't want the user to explicitly provide the services in the constructor, but when I tried to #Autowire the services, I got Autowired members must be defined in valid Spring bean. I could Annotate my builder with #Component, but that would make it a singleton which will not be desirable for a builder.
How can I inject services to my builder class without making it a singleton?
To use the example from this article, lets say I have the following builder:
BankAccount account = new BankAccount.Builder(1234L)
.withOwner(25324)
.atBranch("Springfield")
.openingBalance(100)
.atRate(2.5)
.build();
I want withOwner to use my UserService to get the actual user from the database given the id number received as a parameter. How would I go about injecting UserService to builder?
There are 2 ways to do that:
1) Put service into withOwner() method
new BankAccount.Builder(1234L)
.withOwner(25324, userService)
2) Add UserService to the Builder and create a builder factory:
#Component
class BuilderFactory {
#Autowire
private UserService user service
BankAccount.Builder newBuilder(Long id) {
return BankAccount.Builder(service, id);
}
}
Usage:
builderFactory.newBuilder(1234L)
.withOwner(25324)
How would I go about injecting UserService to builder?
In your spring bean definitions, you cannot and have not to mix objects managed by Spring and these created by yourself and which Spring is not aware.
While you may make it working but it should be used only in very specific rare cases and generally for legacy/third party dependencies reasons, not in a code where you can change that.
Definitively, you want to inject beans dependencies in beans.
This runtime error message means that you don't respect this rule :
but when I tried to #Autowire the services, I got Autowired members
must be defined in valid Spring bean
About :
I could Annotate my builder with #Component, but that would make it a
singleton which will not be desirable for a builder.
singleton is the default scope but Spring allows you to specify other scopes for a component. Just define it as a prototype bean and it will create a new instance of it at each call.
public class BankAccount{
// ...
#Component
#Scope(value="prototype")
public static class Builder{
//...
}
}
Can "context: componentscan" scan custom annotations? If so, where does it store the scanned beans in application context after scanning? How can I access the results?
We register beans or components in XML configuration file. So Spring can detect those beans, components. Spring also support to auto scan, detect and instantiate beans from pre-defined project package via the annotation. So we don't have to declare in the configuration anymore. For example:
<context:component-scan base-package="abc.controller, abc.service" />
in your Controller or Service, you just have to add annotation like:
#Controller
public class SampleController
#Service
public class SampleService
Spring will know that your SampleController and SamplerService and you can use it as you want.
Some detail here: http://docs.spring.io/spring-javaconfig/docs/1.0.0.M4/reference/html/ch06s02.html
I have an annotation based Spring web application controller which maps XML to an annotated plain old java object. Exemplary code as follows:
#Controller
#RequestMapping("/")
public class Endpoint {
#RequestMapping
public void send(...) {
...
}
...
The mapping is automatically done via Jaxb2RootElementHttpMessageConverter and at the moment it is possible to reference and replace content in the received XML.
My question is, is it possible -- for example via beans.xml -- to configure the Jaxb2RootElementHttpMessageConverter such that the replacement of entities is prevented?
The converter is automatically created by Spring.
If you want to overwrite a bean created by spring you just define your own bean of the same type. Additionally you can mark it #Primary. I haven't tried it with Jaxb2RootElementHttpMessageConverter, but it worked with ObjectMapper as described here :
http://docs.spring.io/spring-boot/docs/current/reference/html/howto-spring-mvc.html#howto-customize-the-jackson-objectmapper
I have application that look like below
without spring (prior)
UI-> service --> javabean
p.s: my ui call service (not using DI) and i want to remain this way
new service()
I want my javabean to do DI for certain bean from applicationcontext.xml file.
Should i use Applicationcontext.getBean(the ..xml) file in javabean or is there any better way to do it without changing the service layer and only modify the javabean in bold?
You should look at #Configurable annotation (Tutorial).
The basic idea is that you add this annotation to your bean class. It will then inject any properties as soon as you create a new instance:
#Configurable
public class Person {
private IPeopleDAO _dao;
// SNIP
public save() {
_dao.save(this);
}
}
// use it like this
new Person("john", "doe").save();