I have read an article about mapping an DTO class to an entity. In the article, it manages to create a very general and extensible way of mapping DTO using annotations and RequestResponseBodyMethodProcessor. I have been creating a SOAP service using Spring Boot + Apache CXF. The service is still in an early stage, but it will get really big in the following months. The DTO pattern in the article seems to be a good choice for separating what the client sends and what is stored in the database. I have tried multiple ways of implementing it in the project, but none worked properly. I know RequestResponseBodyMethodProcessor is only used for #RequestBody and #ResponseBody, so I tried putting it in the SOAP Service, but Spring seems to ignore it completely. I have also done some search and maybe the problem comes from the fact CXF uses JAXB and Spring uses Jackson. If this is the case, is there any way to integrate CXF to use Jackson? If the problem isn't JAXB and Jackson, is there any other way of implementing the above pattern for a SOAP service? Just for completeness, the project is Java 1.8, the SOAP service is created using #WebService and the service is published through an WebServiceConfiguration class. Example code of how the code looks like:
#WebService
#Service
public interface MyService {
#WebMethod
public void myEndpoint(#WebParam(name = "someClass") SomeClass someClass);
// others endpoints
}
#Configuration
public interface WebServiceConfiguration {
#AutoWired
private MyServiceImpl myServiceImpl;
#Bean
public ServletRegistrationBean<CXFServlet> servletRegistrationBean(ApplicationContext context) {
return new ServletRegistrationBean<>(new CXFServlet(), "/service/*");
}
#Bean(name = Bus.DEFAULT_BUS_ID)
public SpringBus bus() {
return new SpringBus();
}
#Bean
public Endpoint myService() {
Edpoint endpoint = new EndpointImpl(bus(), myServiceImpl);
endpoint.publish("/myService");
return endpoint;
}
}
Related
With spring boot 2.6.0 (or above) is it possible to generate a rest client from a a controller interface?
Im wondering if its possible to build spring application like this following use case.
Spring application A needs to call spring application B rest interface
Spring application B is a multimodule project that produces server jar, and a api jar
Spring application A imports the B's API jar
Spring application A uses controller interface from B Api jar to make a rest client based on spring annotations.
B Api jar:
#RestsController
public interface MyApplicationAPI {
#GetMapping("/api/some-endpoint)
public SomeDto someEndpoint(SomeDTO obj);
}
B server jar:
public class BApplicationAPIImpl implements MyApplicationAPI {
public SomeDto someEndpoint(SomeDTO obj) {
return xxx;
And finally within A application:
MyApplicationAPI restClient = Some.magic(MyApplicationAPI.class, "http://bappurl.com")
SomeDto response = restClient.someEndpoint(param);
I believe that framework RestEasy supports similar approach, but you have to rely on JAXRS annotations.
Is there anything like that for spring framework? Or even better is there anything like this within spring already - i would prefer to rely on spring inhouse libraries and tools, rather than importing entire resteasy and jaxrs.
Spring Framework 6 (and Spring Boot 3) will have declarative HTTP interfaces (see documentation). However, they won't use the same annotations as controllers, but separate ones. So your example where you use the same interface for both controller and client won't be possible.
Code snippet from the documentation:
interface RepositoryService {
#GetExchange("/repos/{owner}/{repo}")
Repository getRepository(#PathVariable String owner, #PathVariable String repo);
// more HTTP exchange methods...
}
Initialization (the Some.magic() part in your question) can be done with WebClient. As can be seen in the same documentation:
WebClient client = WebClient.builder().baseUrl("https://api.github.com/").build();
HttpServiceProxyFactory factory = WebClientAdapter.createHttpServiceProxyFactory(client);
factory.afterPropertiesSet();
RepositoryService service = factory.createClient(RepositoryService.class);
I am writing a small CRUD in Spring and Java. And I want to use a separate file for writing logic, this is very convenient for me, I did this when developing with NestJS. I have a few questions, is it correct to do this in Spring, or should I do everything inside a function in the controller. And if I write logic in a separate file, I should mark the logic class as #Component and the functions inside it as #Bean, right? I am new to Spring and as I understand it, I have to do this in order for the application to work correctly and my functions to be in the application context.
AuthLogic.java
#Component
public class AuthLogic {
#Bean
public void register() {
// code ...
}
}
AuthController.java
#RestController
public class AuthController {
#RequestMapping(value = "/register", method = RequestMethod.POST)
#ResponseStatus(HttpStatus.CREATED)
public void register(#Valid #RequestBody UserDTO newUser) {
// here I call the register function from AuthLogic
}
}
you can mark your logic class with #Service and use that for example you can make a AuthService and use it like
#Service
public class AuthService{
public returnType login(){
//Logic
}
}
and use this like
#RestController
public class AuthController {
AuthService authService;
#RequestMapping(value = "/register", method = RequestMethod.POST)
#ResponseStatus(HttpStatus.CREATED)
public void register(#Valid #RequestBody UserDTO newUser) {
authService.login();
}
}
You can write your business logic in a new separate file at service layer.
Suppose you name it as AuthService and you mark it with annotation #Service.
#Service
public class AuthService{
}
You can then Autowire it in your controller class.
#RestController
public class AuthController {
#Autowired
AuthService authService;
#RequestMapping(value = "/register", method = RequestMethod.POST)
#ResponseStatus(HttpStatus.CREATED)
public void register(#Valid #RequestBody UserDTO newUser) {
// here I call the register function from AuthLogic
}
}
Using separate files, or classes more importantly, is very recommended in Spring, and I assume most other languages.
The #Bean annotation on AuthLogic.java is unneeded and I think may cause startup or compilation errors.
I would change the name of AuthLogic to AuthLogicImpl, create an interface named AuthLogic with the method signature void register(), and have AuthLogicImpl implement AuthLogic. Then you can create a constructor for AuthController which accepts and AuthLogic parameter and sets it to a private field (note using the interface not the implementation in the constructor).
At the core of Spring is the IoC container. This container holds "beans" that can be injected or autowired into other beans. These beans are an instance of their class and can be used by other beans. Remember Spring uses the singleton pattern, so your beans should be stateless. This allows Spring to handle the application startup for you, so you don't need to write a ton of code creating all the different services/classes and wiring them together, it's all automagically done for you.
There are two key annoitations that you appear to be confused about:
#Component Putting this above a class will create an instance of that class (a bean) and put it into the IoC container. Other beans can access this by accepting the original beans interface in its constructor. So if I put #Component above my class FooImpl which implements Foo, then I can create a class, BarImpl with the constructor public BarImpl(Foo foo) {this.foo = foo} and BarImpl can use any public method of Foo (which will use FooImpl's implementation).
#Bean this is to be put on a method of a class that is annotated with #Configuration. This tells Spring that this method should be run at startup, and this method will return a bean that Spring should add to the IoC container. This is a popular way of configuring a bean that requires some parameters, such as the bean that manages the connection to a third party service or datastore, especially when that there is a little bit of logic that needs to go into creating the bean.
Note that the above is very broad, and there are some specifics if you need to dig deep into the spring framework, so there will be more clarification in the Spring documentation or you dig into some established Spring project. However it should suffice to answer the broad question of what is going on with #Component and #Bean.
There is no specific layout or code structure for Spring Boot Projects. However, there are some best practices followed by developers that will help us too. You can divide your project into layers like service layer, entity layer, and repository layer.
We use the entity layer to write all model and POJO classes. We annotate them with #Entity.
We use #Repository to indicate that this is a repository interface that is used to do some basic CRUD operations.
Sidenote:- You don't have to write #Repository for classes that implement or interfaces that extends Repository interfaces provided by Spring Boot framework.
We use #Service to say that this is the service class where your all business logic will be present.
We use the controller layer to receive HTTP requests and send back HTTP Responses or views.
You can learn and understand more from here
You can refer to this Image to understand the structure
project structure
I have a Feign client that requests a token from a microservice.
Since I am making multiple calls, I would like to cache the responses received from the Feign client and use Spring Guava caching, but it doesn't seem to work. All I have is the configuration class and the annotation on the Feign client.
I read somewhere on stack overflow that Feign might not support #Cacheable annotation. Is this true?
Finally, I managed to solve my issue.
What I did in the end is :
-> Create new #Service annotated class
-> Inject interface with #FeignClient annotation
-> Put all #Cache related annotations ( using #Caching annotation) on the method that calls methods from the interface.
It works! :)
Annotating Feign clients with #Cacheable now works out of the box with Spring Cloud OpenFeign, as per the documentation, since version 3.1.0 (as part of Spring Cloud 2021.0.0).
You only need to make sure that:
you have configured #EnableCaching
you are using spring-cloud-starter-openfeign 3.1.0+ in your dependencies, so this normally means importing spring-cloud-dependencies version 2021.0.0+ (they switched to calver in 2020)
you are using Spring Boot 2.4.1+ (required for this version of Spring Cloud)
What Bianca supposed to do is to add a #Service annotated class to her project where she can use #cacheable annotation.
The traditional way to use FeignClient is to have only an interface annotated with #FeignClient, and then call these methods form other projects/classes. She has added a #Service annotated class, where she call her feignclients methods caching whatever she want.
Traditional:
FeignClient class:
#FeignClient(name="my_feign-client", url = "http://myurl.com/")
public interface MyFeignClient {
#GetMapping("/test")
public ResponseEntity<String> test() throws FeignException;
Class where to call feign client method:
public class TestClass {
#Autowired
private MyFeignClient myFeignClient ;
public String callTest() {
...
return myFeignClient.test();
}
Bianca's method:
Feign client class remains the same.
Service class with cache:
#Service
#CacheConfig(cacheNames={"test"})
public class TestService {
#Autowired
private MyFeignClient myFeignClient ;
#Cacheable
public String callCachedTest() {
...
return myFeignClient.test();
}
And last, the class to call the cached method, that call feignClient:
public class TestClass {
#Autowired
private TestService testService ;
public String callTest() {
...
return testService.callCachedTest();
}
I'm trying to validate my JPA Entity with #Valid like this:
public static void persist(#Valid Object o)
It worked fine for a while but now it stopped working and I'm not sure why. I tried to do it manually inside the persist method, and it works as expected:
ValidatorFactory factory = Validation.buildDefaultValidatorFactory();
Validator validator = factory.getValidator();
Set<ConstraintViolation<Object>> constraintViolations = validator.validate(o);
if (!constraintViolations.isEmpty()) {
throw new ConstraintViolationException(constraintViolations);
}
What could be happening or how can I debug this?
Method Validations is only available starting in bean validation v 1.1 (e.g. hibernate validator 5.x impl) which is part of Java EE 7 only. On top of that to have it working without extra specific BV code your method must be part of a component which is integrated with bean validation (eg. CDI Beans, JAX-RS Resource). Your custom code works because you do not use method validation but rather BV constraints which are defined directly on your object.
Won't work on arbitrary services. In Jersey it will only work for resource methods. So validate the incoming DTO in your resource method.
#POST
public Response post(#Valid SomeDTO dto) {}
See more at Bean Validation Support
UPDATE
So to answer the OP's comment about how we can make it work on arbitrary services, I created a small project that you can plug and play into your application.
You can find it on GitHub (jersey-hk2-validate).
Please look at the tests in the project. You will find a complete JPA example in there also.
Usage
Clone, build, and add it your Maven project
public interface ServiceContract {
void save(Model model);
}
public class ServiceContractImpl implements ServiceContract, Validatable {
#Override
public void save(#Valid Model model) {}
}
Then use the ValidationFeature to bind the service
ValidationFeature feature = new ValidationFeature.Builder()
.addSingletonClass(ServiceContractImpl.class, ServiceContract.class).build();
ResourceConfig config = new ResourceConfig();
config.register(feature);
The key point is to make your service implementation implement Validatable.
The details of the implementation are in the README. But the gist of it is that it makes use of HK2 AOP. So your services will need to be managed by HK2 for it to work. That is what the ValidationFeature does for you.
I have recently wrote a very simple Restful service deployed to JBoss AS 7.
I have a JAX-RS interface defiled as (using scala):
#Provider
#Path("/customers")
trait ICustomerService {
#GET
#Path("/{id}")
#Produces(Array("application/xml"))
def getCustomer(#PathParam("id") id: Int): StreamingOutput
}
And a class implements it (using scala):
class ServiceFacade extends ICustomerService {
val ctx = new ClassPathXmlApplicationContext("orderservice.xml")
val customerService = ctx.getBean("customerService").asInstanceOf[CustomerService]
def getCustomer(id: Int): StreamingOutput = {
customerService.getCustomer(id)
}
}
Here the problem comes. Everytime I issue a request from a client browser, a new ServiceFacade is created by Jboss, thus the Spring xml file is parsed once.
Is there anyway I can create the ServiceFacade myself in a spring config and simply let JBoss uses it rather than create for every single clieng request?
Many thanks.
You are creating a new Spring context on every instance creation of your ServiceFacade, Try either injecting the context or creating a singleton. I don't believe JAX-RS or RestEasy gurantees only a single instance of a annotated class is created.
Also, I am just getting up to speed on Scala myself, but should you not place the annotations on the implementation and not the trait?