Update Views With Spring MVC And Thymeleaf Without Redeploy The App - spring

I am using Spring MVC 3.2, Thymeleaf, Thymeleaf dialect with Tomcat and every time that I change a view I don't want redeploy my app. As suggested from others I am setting:
<property name="cacheable" value="false"/>
in the template resolver, but it not working.
Also a full reload (CTRL + F5) has not effect.
Here my full Thymeleaf configuration:
<!-- Thymeleaf template engine -->
<bean id="templateResolver"
class="org.thymeleaf.templateresolver.ServletContextTemplateResolver">
<property name="prefix" value="/WEB-INF/templates/" />
<property name="suffix" value=".html" />
<property name="templateMode" value="HTML5" />
<property name="cacheable" value="false"/>
</bean>
<bean id="templateEngine"
class="org.thymeleaf.spring3.SpringTemplateEngine">
<property name="templateResolver" ref="templateResolver" />
<!-- These lines add the dialect to Thymeleaf -->
<property name="additionalDialects">
<set>
<bean class="nz.net.ultraq.thymeleaf.LayoutDialect"/>
</set>
</property>
</bean>
<bean class="org.thymeleaf.spring3.view.ThymeleafViewResolver">
<property name="templateEngine" ref="templateEngine" />
</bean>
Is there something else that I can do to resolve this issue?

It depends on many many things and mainly on "where and how" you update your view. If you are using a IDE (Netbeans or Eclipse) it main depend on the IDE itself and on the deployement process.
Current organization on disk :
Source directories => [ on build ] => target or build directories => [ on deploy ] => tomcat directories
But IDE often tries to be developper's friendly and it can happen that target directories and tomcat directories are the same. But it also may depend of the IDE and its configuration.
Also when you save files under source webapp, the IDE may automatically copy them to target.
But this is not guaranteed by <property name="cacheable" value="false"/> of Thymeleaf config. All what it guarantees is that if a template is changed in tomcat directories, next request will use it.
So to be sure where the problem really comes, you will have to find where tomcat actually gets the templates and if those templates are modified.
(and I didn't even talked of browsers cache ...)

In Tomcat "Server Options", check "Serve modules without publishing" did the trick for me.

Related

FileReadingMessageSource.WatchServiceDirectoryScanner: turn off recursive descent into sub-directories?

Versions:
Spring: 5.2.16.RELEASE
Spring Integrations: 5.3.9.RELEASE
macOS Big Sur: 11.6
I am using XML to set up the directory scanner FileReadingMessageSource.WatchServiceDirectoryScanner like so:
<int-file:inbound-channel-adapter id="channelIn" directory="${channel.dir}" auto-create-directory="false" use-watch-service="true" filter="channelFilter" watch-events="CREATE,MODIFY">
<int-file:nio-locker ref="channelLocker"/>
<int:poller fixed-delay="${channel.polling.delay}" max-messages-per-poll="${channel.polling.maxmsgs}"></int:poller>
</int-file:inbound-channel-adapter>
with the following bean definitions:
<bean id="channelLocker" class="org.springframework.integration.file.locking.NioFileLocker"/>
<bean id="channelFilter" class="org.springframework.integration.file.filters.ChainFileListFilter">
<constructor-arg>
<list>
<bean class="org.springframework.integration.file.filters.SimplePatternFileListFilter">
<constructor-arg value="SpreadSheets*.xls" />
</bean>
<bean id="filter" class="org.springframework.integration.file.filters.LastModifiedFileListFilter">
<property name="age" value="${channel.filter.age}" />
</bean>
<ref bean="persistentFilter" />
</list>
</constructor-arg>
</bean>
<bean id="persistentFilter" class="org.springframework.integration.file.filters.FileSystemPersistentAcceptOnceFileListFilter">
<constructor-arg index="0" ref="metadataStore" />
<constructor-arg index="1" name="prefix" value="" />
<property name="flushOnUpdate" value="false" />
</bean>
If I look at logs for org.springframework.integration.file.FileReadingMessageSource, I notice that we register both the specified directory (ie, ${channel.dir}) as well as any of its sub-directories. That is, I see logs like this:
15:44:45.706 [main] DEBUG org.springframework.integration.file.FileReadingMessageSource - registering: /Users/kc/scan.here for file events
15:44:45.711 [main] DEBUG org.springframework.integration.file.FileReadingMessageSource - registering: /Users/kc/scan.here/and.here for file events
I've looked Spring docs as well as API docs for the relevant software modules (Eg, FileReadingMessageSource), but I don't see any property or configuration option for turning off recursive descent into sub-directories.
What is the recommended practice here for scanning only files within the specified directory, but not recursing any deeper than that?
If you don't a recursion and scan the whole file tree, just don't use that watch service!
For the create and modify events you can configure a FileSystemPersistentAcceptOnceFileListFilter which checks for the file.lastModified(). I see you do that anyway, therefore it is not clear why do you need a watch service at all?
See some related discussed here: https://github.com/spring-projects/spring-integration/issues/3557.
If you still have some reasonable argument to use watch service for only a root dir, please add a comment into that issue and we will revise it respectively.

How do I automatically reload my properties in my Spring XML appilcation context?

I’m using Spring 3.2.11.RELEASE. I currently have the following set up in my application context file for the purposes of loading a cron trigger based off a schedule defined in a properties file (the property = cron.schedule) …
<bean id="localPropertyConfigurer"
class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="location">
<value>classpath:application.properties</value>
</property>
</bean>
…
<bean id="updateResourcesJob" class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean">
<property name="targetObject" ref="myService" />
<property name="targetMethod" value="myMethod" />
<property name="concurrent" value="true" />
</bean>
<bean id="updateResourcesCronTrigger" class="org.springframework.scheduling.quartz.CronTriggerBean">
<property name="jobDetail" ref="myJob" />
<property name="cronExpression" value="${cron.schedule}" />
</bean>
My question is, I would like to create an XML configuration in my context file that allows me to edit my properties file and have everything automatically reloaded without having to restart my server or re-deploy my application. I have read several places about Apache Commons Configuration, but I can’t figure out how to take the above and rewrite an XML config that would utilize the configuration.
Thanks for any help, - Dave

How to internationalize REST Spring-MVC application?

I am new with spring and I still don't know well about hierarchy and terminology of spring. I am implementing a RESTful app with spring. After searching and reading about how to internationalize spring, I tried to do it in my app. But it seems to me it is not configured properly. Because I get exception. I would like to show you the screenshot of my project structure. And I would like to ask you why my applicationContext.xml show a problem exist.
spring-servlet.xml
<!-- SPRING INTERNALIZATION CONFIGURATION -->
<bean id="messageSource" class="org.springframework.context.support.ReloadableResourceBundleMessageSource">
<property name="basename" value="classpath:messages" />
<property name="defaultEncoding" value="UTF-8"/>
</bean>
<bean id="localeResolver" class="org.springframework.web.servlet.i18n.CookieLocaleResolver">
<property name="defaultLocale" value="en"/>
</bean>
<bean id="localeChangeInterceptor" class="org.springframework.web.servlet.i18n.LocaleChangeInterceptor">
<property name="paramName" value="language" />
</bean>
<bean id="handlerMapping" class="org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping">
<property name="interceptors">
<ref bean="localeChangeInterceptor" />
</property>
</bean>
The javadoc of ReloadableResourceBundleMessageSource.setBaseNames() says:
Set an array of basenames, each following the basic ResourceBundle convention of not specifying file extension or language codes, but in contrast to ResourceBundleMessageSource referring to a Spring resource location: e.g. "WEB-INF/messages" for "WEB-INF/messages.properties", "WEB-INF/messages_en.properties", etc.
But you've placed your message properties files under src/main/resources in the Maven project structure, so they will end up at the root of the classpath instead (which means that even if Spring looked for them in the classpath, the /resources prefix you've used in the configuration would prevent Spring to find them).
So place the properties file under WEB-INF, and use WEB-INF/messages as the basenames property.

deployment for different environments with maven and spring

I've got two properties files:
environment.properties:
- project.host.db3.database.name=oracle
application.properties:
- database.name=${project.host.db3.database.name}
The first one represents the environment variables and the second one the properties to be used in a spring project, in this configuration i try to set the environment.properties but of course it doesn't work:
<bean id="systemPropertiesLoader"
class="org.springframework.beans.factory.config.MethodInvokingFactoryBean">
<property name="targetObject" value="#{#systemProperties}" />
<property name="targetMethod" value="putAll" />
<property name="arguments">
<util:properties location="classpath:environment.properties" />
</property>
</bean>
<bean id="propertyPlaceholderConfigurer"
class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"
depends-on="systemPropertiesLoader">
<property name="locations">
<list>
<value>classpath:application.properties</value>
</list>
</property>
<!-- bean using database.name -->
Is it doable?, and if not, how do people have agnostic properties in their projects (like database.name), and only one file (war, jar, etc.) to be deployed?
Well, it seems it's doable for beans xml defined as long as you define your properties it like this:
<bean id="propertyPlaceholderConfigurer"
class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"
depends-on="systemPropertiesLoader">
But if you ever try to access the properties from a servlet:
this.getClass().getClassLoader().getResourceAsStream("application.properties");
chances are you get this:
bad port configuration: ${project.host.db3.database.port}
java.lang.NumberFormatException: For input string: "${project.host.db3.database.port}"
In answer to yorkw, now i can have the same war to be deployed in several environments and configure the host with -Denvironment=development, so i can deploy a properties file for development, production, etc. and simply use:
<bean id="systemPropertiesLoader"
class="org.springframework.beans.factory.config.MethodInvokingFactoryBean">
<property name="targetObject" value="#{#systemProperties}" />
<property name="targetMethod" value="putAll" />
<property name="arguments">
<util:properties location="classpath:**${environment}/**environment.properties" />
</property>
</bean>
Otherwise i should have the application.properties substituted before deployment for every environment. I'm sure there are better solutions than this.

using the MergingPersistenceUnitManager to load entity

I have a project setup where i have a module which is present in the WEB-INF/lib folder of the parent war file. This module contains a persistence.xml and an entity which i need to be loaded when the JPA container loads during startup. Somehow i need to merge the persistence units of the war and the lib jar. the persistence.xml of my war is present in WEB-INF/classes/META-INF hence it would take WEB-INF/classes as the persistence root and wouldnt understand the entity from my lib jar. That i found out the hard way.
I stumbled across multiple people suggesting solutions to this problem
http://ancientprogramming.blogspot.com/2007/05/multiple-persistencexml-files-and.html
And i also found out that there is Spring's Data-jpa project which has a MergingPersistenceUnitManager which will merge the class definitions of the entities.
Here is my configuration
<bean id="pum" class="org.springframework.data.jpa.support.MergingPersistenceUnitManager">
<property name="persistenceXmlLocations">
<list>
<value>classpath*:META-INF/persistence.xml</value>
</list>
</property>
<property name="defaultDataSource" ref="dataSource"></property>
</bean>
<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="persistenceUnitName" value="LineManagement" />
<property name="persistenceUnitManager" ref="pum"></property>
<property name="jpaVendorAdapter">
<bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
<property name="generateDdl" value="false" />
<property name="showSql" value="false" />
<property name="databasePlatform" ref="cpsHibernateDialectClassName" />
</bean>
</property>
which doesnt work. It gives me an error
java.lang.NoSuchMethodError:org.springframework.data.jpa.support.MergingPersistenceUnitManager.getPersistenceUnitInfo(Ljava/lang/String;)Lorg/springframework/orm/jpa/persistenceunit/MutablePersistenceUnitInfo;
I have no clue how it gives me this error. From my understanding the MergingPersistenceUnitManager extends the DefaultPersistenceManager. Only thing i suspect is that there might be a conflict.
Here are my dependencies. spring-orm-3.0.2-RELEASE.jar and spring-data-jpa-1.0.3-RELEASE.jar.
I can go back to the ancient programming solution, but shouldnt it just work out of the box?
You have mismatching versions of spring-orm and spring-data-jpa. In general arbitrary versions are not guaranteed to play well together.
MutablePersistenceUnitInfo getPersistenceUnitInfo - method is absent from the MergingPersistenceUnitManager (or actually from it's superclass DefaultPersistenceUnitManager) in version orm version 3.0.2.
From same class in version 3.0.5 you can find this method: DefaultPersistenceUnitManager.java Also maven pom for spring-data-jpa-1.0.3 lists dependency to spring-orm 3.0.5. So your problem is solved by using sprin-orm version 3.0.5.

Resources