Issue with Static resources when extending Spring Boot WebMvcConfigurationSupport - static

I extended WebMvcConfigurationSupport to implement an api versioning scheme - i.e.
#Configuration
public class ApiVersionConfiguration extends WebMvcConfigurationSupport {
#Override
public RequestMappingHandlerMapping requestMappingHandlerMapping() {
return new ApiVersionRequestMappingHandlerMapping(readDateToVersionMap());
}}
This uses a custom handler mapping to version the api and works quite nicely.
However it also seems to disable the #EnableAutoConfiguration bean so that now static resources aren't served (as mentioned in this question Is it possible to extend WebMvcConfigurationSupport and use WebMvcAutoConfiguration?).
Ok, I thought, let's just add a resource handler to the class above - i.e.
#Configuration
public class ApiVersionConfiguration extends WebMvcConfigurationSupport {
#Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("classpath:/public/").addResourceLocations("/");
}
#Override
public RequestMappingHandlerMapping requestMappingHandlerMapping() {
return new ApiVersionRequestMappingHandlerMapping(readDateToVersionMap());
}}
However.. this isn't working..? I get this error when I browse to /index.html:
No mapping found for HTTP request with URI [/index.html] in DispatcherServlet with name 'dispatcherServlet'
..If I disable this class then these resources are served just fine by #EnableAutoConfiguration magic.
I've been playing with various options to serve static content having extended the WebMvcConfigurationSupport and thus far no success.
Any ideas?

I was facing the same problem and came up with a solution that just works for me. If you just want to get the resources working without worrying of repetition you can do:
#Configuration
public class StaticResourcesConfig extends WebMvcAutoConfigurationAdapter {
}
and then
#Configuration
#EnableWebMvc
#Import(StaticResourcesConfig.class)
public class WebConfig extends WebMvcConfigurationSupport {
...
}
This successfully uses the Spring Boot defaults for serving static resources, as long as you don't map /** in your controllers.

Related

Using Project Reactor with Apache Camel

I'd like to know if it is possible to use Project Reactor with Apache Camel, so applications be fully reactive and non-blocking IO. I'd like to know how does the Project Reactor support works when integrating other Apache Camel's components.
Can I read for example from S3 reactively (therefore I'll need to use the Async S3 client behind the scenes)? Or will I block when reading from S3 and then just create a Flux out of what has been returned?
Where reactiveness is needed, you should use the relevant spring and reactor libraries. there are pseudo camel code also u can db call in camel bean or processors etc
#RestController
#RequestMapping(value = "/api/books")
#RequiredArgsContructor
public class HomeController {
private final BookRepository bookRepository;
private final ProducerTemplate template
#GetMapping("")
public Flux<Book> getHome() {
List <Book> books=bookRepository.findAll();
X ret = template.requestBody("direct:something", books, X.class);
}
}
#Component
public class SomeRoute extends RouteBuilder {
#Override
public void configure() throws Exception {
from("direct:something")
.process(e-> {
List<Book> books = e.getIn.getBody(List.class)
// some logic
e.getIn.setBody(new X( ))
})
}

Extending Camel DSL

I have a route with a custom aggregator, it looks like this:
I would like to wrap the details so that developers can just add a single line to their routes to get the functionality. Can I wrap those lines so that I have a class that extends ProcessorDefinition, and then add that ProcessorDefinition to routes that need it, so that it looks like an extension of the DSL? If yes, is the addOutput() method the way to do this?
Something like this:
from("file:" + FILE_PATH + "?noop=true")
.log("Detected file")
.split().tokenize("\n")
.streaming()
.unmarshal(bindy)
.addProcessorDefinition(new MyCustomAggregation())
.to("direct:handleAggregatedRecords");
Where
MyCustomerAggegation extends ProcessorDefinition
I have a similar use-case and I don't think Camel has anything to offer out of the box to extend routes at a certain point with route fragments. However, you can break apart one route into multiple fragments
public abstract class ExtensibleRouterBuilder extends RouteBuilder {
#Override
public void configure() {
ProcessorDefinition<?> routeFragmentToExtend= from("file:" + FILE_PATH + "?noop=true")
.log("Detected file")
.split().tokenize("\n")
.streaming()
.unmarshal(bindy);
configure(routeFragmentToExtend);
routeFragmentToExtend.to("direct:handleAggregatedRecords");
}
//"Users" of your API can implement and extend your route
public abstract void configure(ProcessorDefinition<?> from);
}
But this can get messy, especially if you have several choice() calls, so I wish Camel enhances it's API one day.
To get a similar outcome, I use Lombok #ExtensionMethod in the following way:
#ExtensionMethod(MyRouteBuilder.Extensions.class)
public class MyRouteBuilder extends RouteBuilder {
#Override
public void configure() {
from("direct:in")
.debugLog("Incoming message ${body}");
}
#UtilityClass
public static class Extensions {
public static ProcessorDefinition<?> debugLog(
#NonNull ProcessorDefinition<?> route, String logMessage) {
return route
.log(LoggingLevel.DEBUG, "debug-logger", logMessage);
}
}
}

Camel-Cdi not injecting CamelContext with Registery

I am using camel-cdi and it is injecting the CamelContext, detecting all the routes in project.
But I want a CamelContext with a registry because I have some components that I use in camel routes like shown below.
SimpleRegistry registry = new SimpleRegistry();
registry.put("actionProcessor", actionProcessor);
registry.put("jpa", jpaComponent);
registry.put("jtaTransactionManager", platformTransactionManager);
CamelContext camelContext = new DefaultCamelContext(registry);
When I inject CamelContext the components like actionProcess, jpa are not recognized. when in my Route I have
.to("bean:actionProcessor?method=myMethod(${body})")
but my bean does not get executed.
I documentation I read use # before components name which are in registry but still it is not working.
Please suggest how can I achieve this using camel-cdi.
Did you already try with creating a CdiCamelContext (a subclass of DefaultCamelContext) ?
Otherwise, a more elegant would be to annotate your various classes, eg:
#Named("actionProcessor")
public class MyActionProcessor{
...
}
We have been using this for years without any problem
public class ContextFactory {
#Produces
#ApplicationScoped
#ContextName("Demo")
static final CamelContext createContext() {
CdiCamelContext context = new CdiCamelContext();
context.setStreamCaching(true);
context.disableJMX();
return context;
}
}
#ContextName("Demo")
public class MyRouteBuilder extends RouteBuilder {
from("...")
.to("bean:actionProcessor?method=myMethod")
}
#Named("actionProcessor")
public class MyActionProcessor{
public void myMethod(#Body String body) {}
}
Of course, in order to work, you need to activate the JEE bean discovery (=add a "beans.xml" file in META-INF or WEB-INF) !

#EnableAspectJAutoProxy not work with proxyTargetClass=false

I am learning about Spring AOP at first time.
I am reading about in this sites:
Site2 and
Site1
Following this I have made the next classes
Main class:
public class App {
public static void main(String[] args) {
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
context.register(AppConfig.class);
context.refresh();
MessagePrinter printer = context.getBean(MessagePrinter.class);
System.out.println(printer.getMessage());
}
}
App config class:
#Configuration
#ComponentScan("com.pjcom.springaop")
#EnableAspectJAutoProxy(proxyTargetClass=true)
public class AppConfig {
#PostConstruct
public void doAlert() {
System.out.println("Application done.");
}
}
Aspect class:
#Component
#Aspect
public class AspectMonitor {
#Before("execution(* com.pjcom.springaop.message.impl.MessagePrinter.getMessage(..))")
public void beforeMessagePointCut(JoinPoint joinPoint) {
System.out.println("Monitorizando Mensaje.");
}
}
And others...
Just like that app work nice, but if I put proxyTargetClass to false. Then I get the error below.
Exception in thread "main" org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [com.pjcom.springaop.message.impl.MessagePrinter] is defined
at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBean(DefaultListableBeanFactory.java:318)
at org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.java:985)
at com.pjcom.springaop.App.main(App.java:18)
Why?
#EnableAspectJAutoProxy(proxyTargetClass=false)
Indicates that JDK dynamic proxy will be created to support aspect execution on the object. And therefore as this type of proxy requires a class to implement an interface your MessagePrinter must implement some interface which declares method getMessage.
#EnableAspectJAutoProxy(proxyTargetClass=true)
On the opposite instruct to use CGLIB proxy which is able to create proxy for a class without an interface.
1> Message Printer has to be defined as a component i.e :
`
package com.pjcom.springaop.message.impl;
#Component
public class MessagePrinter{
public void getMessage(){
System.out.println("getMessage() called");
}
}`
in the same package as configuration java file if no #ComponentScan is not defined for some other packages.
2> If same type of bean class has many other dependencies then to resolve dependencies in spring Config use #Qualifier annotation.

GAE - rpc and HashMap<K,V> field

I tested my gwt app in eclipse and it worked fine; Then I tried to deploy my test app to gae... That what exception I can see in gae logs after each rpc call :
java.lang.RuntimeException: java.io.NotSerializableException
... so I am still looking the reason; but there is a point which make me confused cause one of my rpc-callback objects contains HashMap as one of its fields;
public abstract class Report implements Serializable{}
public abstract class Message implements Serializable{}
public class ErrorMessage extends Message{}
public final class Error extends Report
{
private HashMap<String,ErrorMessage> msgs;//<---?
//...
public void setMsg(HashMap<String,ErrorMessage> msgs){this.msgs=msgs;}
public HashMap<String,ErrorMessage> getMsg(){return this.msgs;}
}
...So my question is...
does gae supports java.util.HashMap ? And if not what is the most optimal collections alternative?
Thanks
It might be the "ErrorMessage" object that's not serializable.

Resources