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);
Related
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;
}
}
So I have a React app I want to serve from my Spring app (ala this blog). As part of my gradle build task, I run the npm build command and copy the resulting files to /build/resources/main/static. This works fine and I can access my app at mysite.com/index.html, but I want to control who has access more granularly. As such, I applied #EnableWebMvc to my app, but from there, I can't seem to get my API controller to actually serve the view from the build directory. It seems no matter where I put it, it doesn't like serving directly from /build. Any way to make this work?
The handler looks like:
#Controller
class MyController {
#RequestMapping("/")
fun index(): String {
return "index"
}
}
As indicated in the Spring Boot documentation, you do not need - in fact, it is not recommended - to use #EnableWebMvc when using Spring Boot. They state, when describing Spring MVC auto-configuration:
Spring Boot provides auto-configuration for Spring MVC that works well with most applications.
And:
If you want to keep those Spring Boot MVC customizations and make more MVC customizations (interceptors, formatters, view controllers, and other features), you can add your own #Configuration class of type WebMvcConfigurer but without #EnableWebMvc.
In the guide, they continue when describing static content handling:
By default, Spring Boot serves static content from a directory called /static (or /public or /resources or /META-INF/resources) in the classpath or from the root of the ServletContext. It uses the ResourceHttpRequestHandler from Spring MVC so that you can modify that behavior by adding your own WebMvcConfigurer and overriding the addResourceHandlers method.
In your example, following this advice, you can indicate the static resource handling location with something like (sorry, I am not fluent in Kotlin, forgive for write the example in Java):
#Controller
public class MyController implements WebMvcConfigurer {
#Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry
.addResourceHandler("/static/**")
.addResourceLocations("classpath:/static")
;
}
#GetMapping(path = "/")
public String index() {
return "index";
}
}
Please, adapt the paths in addResourceHandlers to your needs.
You can of course place this method in an ad hoc #Configuration.
Having said that, if when you say granular you mean security, the best approach you can take is to configure Spring Security and provide the necessary authorization rules: please, see the relevant documentation.
I have combination of web and core projects under the same maven parent module as like,
Parent
- Web (com.parent.test.web)
- Core (com.parent.test.core)
I would like to refer the web module dependency in the core project to invoke some of the api from web module
Web project sample,
com.test.parent.web
public interface RestInterface {
public ResponseEntity load();
}
#RestController
public class RestInterfaceImpl implements RestInterface {
#Override
#RequestMapping(value = "/getData", method = RequestMethod.GET, produces = APPLICATION_JSON)
public #ResponseBody ResponseEntity<Object> load() {
}
}
Core project sample,
com.test.parent.core
#Component
public class CoreImpl implements CoreInterface {
// Is this possible to autowire
#Autowired
private RestInterface restInterface;
public boolean getOptions() {
ResponseEntity<Object> results = restInterface.load();
for (Object o : results) {
//TODO
}
}
}
Because the projects are developed within the same parent pom module. All the projects will be grouped into a springboot jar and will be deployed into the same environment. So, I'd like to refer the web project dependency into the core project and trying to scan the web classes inside the core project.
I'd like to get clarified on few things ,
Is it the good approach ?
If it is the good approach, how we can implement ?
If not then what will be correct approach ?
IMHO it is definitely not a correct approach. The separation of concerns principle says that controllers should only be small pieces of code that take parameters from the requests, pass them to business classes, and forward to a view that will display the results.
If you need to call some methods of the controller from a core class, it means but you have a Fat Ugly Controller carrying business methods inside it. The correct approach is to separate the web part => controller, from the business part => service layer.
That way you create a service bean that will be autowired in both the (now thin) controller and the other core classes that need to call its methods.
My application uses the Spring Framework 4 included spring-messaging module (with key abstractions from the Spring Integration project such as Message, MessageChannel,MessageHandler and others that can serve as a foundation for such a messaging architecture.)
My application uses Websocket & STOMP. It maintains connections(websocket sessions) with a high volume of java websocket clients & one of the requirements was to use either akka or reactor.
I want to integrate spring-reactor RingBufferAsyncTaskExecutor in place of ThreadPoolTaskExecutor in clientInboundChannelExecutor & clientOutboundChannelExecutor
to get better Throughput. At least I've identified this approach as the way to integrate spring-reactor into my existing application - this may not be the right approach.
I was looking at reactor-si-quickstart, since it demonstrates how to use reactor with spring integration & since spring-messaging in Spring Framework 4 includes key abstractions from the Spring Integration project. I thought it would be the closest reference.
My working java config for web socket has the following class declaration
public class WebSocketConfig extends WebSocketMessageBrokerConfigurationSupport implements WebSocketMessageBrokerConfigurer.
WebSocketMessageBrokerConfigurationSupport extends AbstractMessageBrokerConfiguration.
In org.springframework.messaging.simp.config.AbstractMessageBrokerConfiguration I wanted to try configure RingBufferAsyncTaskExecutor in place of ThreadPoolTaskExecutor
#Bean
public ThreadPoolTaskExecutor clientInboundChannelExecutor() {
TaskExecutorRegistration reg = getClientInboundChannelRegistration().getOrCreateTaskExecRegistration();
ThreadPoolTaskExecutor executor = reg.getTaskExecutor();
executor.setThreadNamePrefix("clientInboundChannel-");
return executor;
}
When I try override this method in WebSocketConfig "The method getOrCreateTaskExecRegistration() from the type ChannelRegistration is not visible" because
in AbstractMessageBrokerConfiguration it's protected ....
protected final ChannelRegistration getClientInboundChannelRegistration() {
if (this.clientInboundChannelRegistration == null) {
ChannelRegistration registration = new ChannelRegistration();
configureClientInboundChannel(registration);
this.clientInboundChannelRegistration = registration;
}
return this.clientInboundChannelRegistration;
}
I don't fully understand the WebSocketMessageBrokerConfigurationSupport hierarchy or the WebSocketMessageBrokerConfigurer interface in my WebSocketConfig. I just played around with overriding what I needed to for my customizations to work.
Not sure if it's relevant, but I don't need an external broker because my application doesn't send any data to all connected subscribers, at the moment and is unlikely to down the line. Communication with daemon type java websocket clients is point-to-point, but the web ui websocket in the browser does use subscribe to get real-time data so it's a convenient setup (rather then spring integration direct channel) and there where clear sources on how to set it up - still I'm not sure it is most efficient application design.
STOMP Over WebSocket Messaging Architecture as described in the spring-framework reference documentation was the most comprehensive approach since this is my first spring project.
Is it possible to get the performance boosts from integrating spring-reactor into my existing application?
Or should I try to use spring integration instead, this would require a lot of modification, as far as I can tell - also it seems illogical that it would be necessary given that Spring Framework 4 included spring-messaging module was from spring integration.
How can should I integrate spring-reactor into my standard spring framework 4 STOMP Over WebSocket Messaging Architecture?
If configuring RingBufferAsyncTaskExecutor in place of ThreadPoolTaskExecutor in clientInboundChannelExecutor & clientOutboundChannelExecutor is the correct way, how should I go about doing this?
Actually the RingBufferAsyncTaskExecutor isn't ThreadPoolTaskExecutor, so you can't use it that way.
You can simply override clientInbound(Outbound)Channel beans from your AbstractWebSocketMessageBrokerConfigurer impl and just use #EnableWebSocketMessageBroker:
#Configuration
#EnableWebSocketMessageBroker
#EnableReactor
public class WebSocketConfig extends AbstractWebSocketMessageBrokerConfigurer {
#autowired
Environment reactorEnv;
#Override
public void registerStompEndpoints(StompEndpointRegistry registry) {
registry.addEndpoint("/ws").withSockJS();
}
#Override
public void configureMessageBroker(MessageBrokerRegistry configurer) {
configurer.setApplicationDestinationPrefixes("/app");
configurer.enableSimpleBroker("/topic", "/queue");
}
#Bean
public AbstractSubscribableChannel clientInboundChannel() {
ExecutorSubscribableChannel channel = new ExecutorSubscribableChannel(new RingBufferAsyncTaskExecutor(this.reactorEnv));
ChannelRegistration reg = getClientOutboundChannelRegistration();
channel.setInterceptors(reg.getInterceptors());
return channel;
}
}
And pay attention, please, to the WebSocket support in the Spring Integration.
By the way: point me out, please, to the link for that reactor-si-quickstart.
I'm deploying Spring based web applications on Amazon's Beanstalk platform, and they give me the option of setting a "healthcheck" URL path for my application.
The idea is that their platform will do a request against that URL, after the deployment, to see if the application is successfully started. So, if the request results in an HTTP 200, the application is probably fine. But if it results in an HTTP 500 or something else, the platform knows there's a problem with the application.
So, I wish I could develop some kind of servlet that would check if the Spring Application Context was successfully initialised, or not, to give an appropriate HTTP response code to the platform.
Has anybody attempted something like this? For similar purposes?
I'm wondering if Spring already provides some elegant solution for this.
I'd suggest using health checks functionality from Metrics. You could set up a number of classes that extend HealthCheck class and implement check() method. These health check implementations would be Spring managed beans themselves and could autowire Spring beans and validate them. Then configure HealthCheckServlet to monitor application state. Also check metrics-spring project. It will make Spring and Metrics integration simpler.
If you are using Java Spring configuration you might have a Metrics config like this that extends MetricsConfigurerAdapter from metrics-spring
#Configuration
#EnableMetrics
public class MetricsConfig extends MetricsConfigurerAdapter { }
And then #Import(value = {MetricsConfig.class}) to your Spring config.
You also need and implementation of ServletContextListener to wire up HealthCheckServlet and Spring. This HealthCheckContextListener should be added to your web.xml
public class HealthCheckContextListener extends
HealthCheckServlet.ContextListener implements ServletContextListener {
private WebApplicationContext context;
public HealthCheckContextListener(WebApplicationContext context) {
this.context = context;
}
public HealthCheckContextListener() {}
#Override
public void contextInitialized(ServletContextEvent event) {
this.context = WebApplicationContextUtils.getRequiredWebApplicationContext(event.getServletContext());
event.getServletContext().setAttribute(HealthCheckServlet.HEALTH_CHECK_REGISTRY,
context.getBean(HealthCheckRegistry.class));
}
#Override
protected HealthCheckRegistry getHealthCheckRegistry() {
return (HealthCheckRegistry) context.getBean(HealthCheckRegistry.class);
}
}
The simplest thing you can do is this:
#Controller
class HealthCheckController {
#ResponseStatus(OK)
#RequestMapping(value = "/ping", method = HEAD) {
public void ping() {
}
}
Extendable to also test particular beans, DataSources etc.
You should consider what constitutes a healthy app for you (e.g., servlet tier? JMS queues? FTP servers? etc.) and have your health check verify those services' availability. Obviously the health check is going to run frequently, so you don't want to initiate expensive operations over and over again.
Spring Boot is a new project that aims to simplify Spring development by favoring convention instead of configuration. They have implemented a "health check" feature that you can add to a project via an Actuator add-in module.
Here's a reference to their Health Check implementation -- it uses a controller class to return "ok" and, if there is a data source, attempts to run a query to confirm that the database is accessible (something like "SELECT .. from dual" in Oracle syntax).
This can easily be done in the spring boot framework. By adding below dependency
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
You can check the service by hitting the below URL.
localhost:serverPort/actuator/health