Spring 3.1 ReloadableResourceBundleMessageSource and Apache Tiles 2.2.2 - spring-mvc

What seemed to be a simple task has turned out to be a few hours of suffering.
I am building a Spring 3.1 MVC application on the JavaEE 6 and Servlet 3.0.1 api without a web.xml file. I have a WebMvcConfiguration class like this fragment:
#Configuration
#EnableWebMvc
#ComponentScan(basePackages = "be.collectortools.collectorsite")
public class MvcConfig extends WebMvcConfigurationSupport {
#Bean
public ReloadableResourceBundleMessageSource messageSourceBean() {
String[] basenames = {"classpath:messages"};
ReloadableResourceBundleMessageSource resourceBundle = new ReloadableResourceBundleMessageSource();
resourceBundle.setBasenames(basenames);
resourceBundle.setDefaultEncoding("UTF-8");
return resourceBundle;
}
}
I have successfully setup Apache Tiles 2.2.2 together with 2 basic controllers.
Now I would like to add ResourceBundles to the working Spring/Tiles application and I can't get them to work.
After searching I found some this that might go wrong:
Do I use fmt:message key="application.header" or should I use spring:message code="application.header" in my JSP pages? The first ignores not found values the second throws errors.
I use ReloadableResourceBundleMessageSource which should be 'better' or at least newer then ResourceBundleMessageSource is this ok?
ReloadableResourceBundleMessageSource loads files from more locations so I have specified classpath:
I placed the messages.properties file in the src/main/resources folder
Is it still correct that, when not adding a locale to the end of a bundle's name, this is used as a (default) fallback? Either way adding the "en_US" locale doesn't help.
The error:
root cause
javax.servlet.jsp.JspTagException: No message found under code 'application.header' for locale 'en_US'.
org.springframework.web.servlet.tags.MessageTag.doStartTagInternal(MessageTag.java:184)
also the war file is not being run inside Eclipse I deploy it manually to my local tomcat 7.0.23. This also allows me to see the deployed file structure more easily and gives me better control.
I have no clue what is I am doing wrong any help would be appreciated.

The MessageSource bean has to be named messageSource not messageSourceBean - if you change your #Bean to the following it should resolve the messages correctly:
#Bean
public ReloadableResourceBundleMessageSource messageSource() {
String[] basenames = {"classpath:messages"};
ReloadableResourceBundleMessageSource resourceBundle = new ReloadableResourceBundleMessageSource();
resourceBundle.setBasenames(basenames);
resourceBundle.setDefaultEncoding("UTF-8");
return resourceBundle;
}

Related

Provider test integration with pact broker for Spring Boot junit5 + configuration in application properties

The pact-jvm-provider-spring states that for junit5 provider test, it is not required to use the spring library.
However, #PactBroker annotation depends on the system properties. Is there a way to get this working for application properties via the Spring Property Resolver. I tried to create something similar to SpringEnvironmentResolver.kt and used it in the context setup. But that did not work.
#Provider("api-provider-app")
#PactBroker
#SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
#ActiveProfiles("test")
public class PactVerificationTest {
#LocalServerPort
private int port;
#Autowired
private Environment environment;
#TestTemplate
#ExtendWith(PactVerificationInvocationContextProvider.class)
void testTemplate(Pact pact, Interaction interaction, HttpRequest request,
PactVerificationContext context) {
context.setTarget(new HttpTestTarget("localhost", port));
context.setValueResolver(new SpringResolver(environment));
context.verifyInteraction();
}
}
I get the following error
Invalid pact broker host specified ('${pactbroker.host:}'). Please provide a valid host or specify the system property 'pactbroker.host'.
Update
After some more searching found out that the setTarget was not working and that needs to be moved to #BeforeEach method.
#BeforeEach
void setContext(PactVerificationContext context) {
context.setValueResolver(new SpringResolver(environment));
context.setTarget(new HttpTestTarget("localhost", port));
}
The following snippet helped it work with #PactFolder annotation. But the #PactBroker with properties is still not working
There is a new module added to Pact-JVM that extends the JUnit5 support to allow values to be configured in the Spring Context. See https://github.com/DiUS/pact-jvm/tree/master/provider/pact-jvm-provider-junit5-spring. It will be released with the next version of Pact-JVM, which will be 4.0.7.

Spring boot app using Grails GSP boot plugin Servlet/Configuration issues

I'm trying to convert a Grails 2 app into a couple of Spring Boot apps, with the re-use for now with all the GSPs. Nice boot plugin created by Lari Hotari & Graeme Rocher
https://github.com/grails/grails-boot
I'm trying to see a way that I can use content negoeation I followed a useful spring blog on the topic and I've been looking into the GspAutoConfiguration See link for more info
Doesn't appear to be a simple way that I can see to still use the GSP Template Engine from the GSP configuration to confgure content negotiation in the MvcConfig in the configureContentNegotiation bean
Gradle.build
def grailsVersion = '2.4.4'
compile "org.grails:grails-gsp-spring-boot:1.0.0"
compile "org.grails:grails-web-gsp:$grailsVersion"
compile "org.grails:grails-web-gsp-taglib:$grailsVersion"
compile "org.grails:grails-web-jsp:$grailsVersion"
compile("javax.servlet.jsp:javax.servlet.jsp-api:2.3.1")
//ensures that the embedded servlet container doesn’t interfere with the servlet container to which the war file will be deployed
providedRuntime 'org.springframework.boot:spring-boot-starter-tomcat:1.2.3.RELEASE'
(snipped ...)
Spring MVC Configuration
#Configuration
public class MvcConfig extends WebMvcConfigurerAdapter {
(snippet...)
#Override
public void configureContentNegotiation(ContentNegotiationConfigurer configurer) {
configurer.favorPathExtension(false)
.favorParameter(true)
.parameterName("format")
.ignoreAcceptHeader(true)
.useJaf(false)
.defaultContentType(MediaType.TEXT_HTML)
.mediaType("json", MediaType.APPLICATION_JSON)
}
/**
* Create the CNVR. Specify the view resolvers to use explicitly. Get Spring to inject
* the ContentNegotiationManager created by the configurer (see previous method).
*/
#Bean
public ViewResolver contentNegotiatingViewResolver(ContentNegotiationManager manager) {
// Define the view resolvers
List<ViewResolver> resolvers = new ArrayList<ViewResolver>();
//NOT this simple due to the way GspAutoConfiguration ovverrides so much view based behaviour
InternalResourceViewResolver r2 = new InternalResourceViewResolver()
r2.setPrefix("/templates/views")
r2.setSuffix(".gsp")
resolvers.add(r2)
JsonViewResolver r1 = new JsonViewResolver()
resolvers.add(r1)
// Create the CNVR plugging in the resolvers and the content-negotiation manager
ContentNegotiatingViewResolver resolver = new ContentNegotiatingViewResolver();
resolver.setViewResolvers(resolvers);
resolver.setContentNegotiationManager(manager);
return resolver;
}
}

what is the equivalence of contextDestroyed() in ServletContainerInitializer?

I have to create a class that implements ServletContextListener to add an event during the initialization or the shutdown of Tomcat. However, the class has to be located in a jar file inside WEB-INF/lib. After doing some readings, I found out that this is not possible, and the alternative is to use ServletContainerInitializer. However, only onStartup() method is available.
Is there any other alternatives where I can also add an event during the shutdown or destruction of the web application?
I am using Tomcat 8 and Java 8 btw.
Let your ServletContainerInitializer programmatically add a ServletContextListener which in turn does the desired job in its contextDestroyed().
servletContext.addListener(YourServletContextListener.class);
Not sure how you tested your code. But this the ServletContextListener works fine for me on Tomcat 8.5.5. Just try this code, no need to put this to separate JAR file.
#WebListener
public class AppContextListener implements ServletContextListener{
Logger log = LoggerFactory.getLogger(AppContextListener.class);
#Override
public void contextInitialized(ServletContextEvent servletContextEvent) {
}
#Override
public void contextDestroyed(ServletContextEvent servletContextEvent) {
log.info("### Context is destroyed ###");
}
}

Configure Spring MVC application to make changes to html files/templates without recompiling

I have a very simple Spring 4.0 Boot project. I would like to start the application and be able to make changes to the html files located in /templates/ on the fly, without having to stop and restart the application. Changes to static assets, like java scripts or css files, is no problem.
Below are the details of my program:
There are no XML configuration files. This class is used for configuration.
#Configuration
public class MVCConfiguration extends WebMvcConfigurerAdapter{
#Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("assets/**")
.addResourceLocations("classpath:/templates/assets/");
registry.addResourceHandler("/css/**")
.addResourceLocations("/css/");
registry.addResourceHandler("/img/**")
.addResourceLocations("/img/");
registry.addResourceHandler("/js/**")
.addResourceLocations("/js/");
}
}
This is my controller.
#Controller
public class ControlFreak {
#RequestMapping(value = "/", method = RequestMethod.GET)
public String index(){
return "index";
}
}
I have index.html located in templates/
I run the application using this class.
#Configuration
#EnableAutoConfiguration
#ComponentScan
public class Application {
public static void main(String[] args) {
ApplicationContext ctx = SpringApplication.run(Application.class, args);
}
}
What you are trying to achieve is easily done using an IDE and will save a heck of a lot of time during development.
First of all you need to configure Spring Boot to not cache Thymeleaf templates by setting:
spring.thymeleaf.cache=false
Then you just need to start the application using the IDE in debug mode (just Debug the class with the main method) and whenever you make change to a Thymeleaf Template you just need to instruct the IDE to reload the project.
In IntelliJ IDEA, that is done from the Reload Changed Classes option in the Run menu.
I think you can configure Eclipse to automatically update the project on each change, but it's been a while since I have used it.
Path to project
project.base-dir=file:///C:/temp/auth/
Templates reloading during development
spring.thymeleaf.prefix=${project.base-dir}/src/main/resources/templates/
spring.thymeleaf.cache=false
Static resources reloading during development
spring.resources.static-locations=${project.base-dir}/src/main/resources/static/
spring.resources.cache-period=0

EJB3.1 classpath issue

I have 2 POJOs, in which one of them is an EJB and the other is a helper class.
//EJB Bean class
#Singleton
#LocalBean
#Startup
public class EJBBean{
#PostConstruct
public void init(){
HelperClass helper = new HelperClass();
helper.init();
}
}
//Helper class
public class HelperClass{
private static Log LOG = LogFactory.getLog("HelperClass");
private static Long currentTime = new Date().getTime();
public void init(){
//Some statements that use Log and do other Initialization
}
}
When I deploy this EJB jar I am getting an error
java.lang.NoClassDefFoundError: org/apache/commons/logging/LogFactory
I have the commons-logging-1.1.1.jar in the classpath; also, I have configured it to use Log4J. As a standalone app that is without EJB meta-data it works fine. Am I missing some EJB config?
BTW I am pretty new to EJB. I am using GlassFish 3.1, Eclipse Helios as IDE and EJB3.1.
This could be because you put the commons-logging-1.1.1.jar into the wrong directory or because your server already provides server-wide library which consists of logging classes.
By the way - I remember a lot of strange 'NoClassDefFoundError' because of mixing commons-logging, log4j and slf4j (especially in mismatching versions).

Resources