Load webserver context.xml using Spring - spring

Fairly new to Spring, so I'm having some trouble with this. I'm trying to use LDAP security with Spring. I can use a properties file I created inside the webapp itself. But what I would like to do is load and read the context.xml file of the server (it has all the values I need for this and other applications).
This is what I have:
<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="ignoreUnresolvablePlaceholders" value="true"/>
</bean>
<bean class="org.springframework.web.context.support.ServletContextPropertyPlaceholderConfigurer">
<property name="systemPropertiesModeName" value="SYSTEM_PROPERTIES_MODE_OVERRIDE"/>
<property name="searchContextAttributes" value="true"/>
<property name="contextOverride" value="true"/>
<property name="ignoreResourceNotFound" value="true"/>
<property name="locations">
<list>
<value>/WEB-INF/properties/dataUploadProperties.properties</value>
<value>/WEB-INF/properties/globalProperties.properties</value>
<value>context.xml</value>
</list>
</property>
</bean>
I'm able to load and read the 2 properties files, but the context.xml is not found. Does it need to be the absolute path on the server?
Thanks
Chris

So the first thing I would recommend is to use Spring Security. It has an already build in LDAP support.
but the context.xml is not found
Normally this (reading the context.xml directly) is not the way you should go.
Instead, define some properties and or JNDI resources in the context.xml and then use them in the spring configuration.
For example:
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:jee="http://www.springframework.org/schema/jee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/jee
http://www.springframework.org/schema/jee/spring-jee-3.0.xsd">
<!-- access via jndi -->
<jee:jndi-lookup id="jndiEmailSession"
jndi-name="java:comp/env/email/session/myEmailSession" />
<!-- direct access for properties required the SERVLET contect property
place older configurer, then it works like properties from normal
property files -->
<bean class="org.springframework.web.context.support.ServletContextPropertyPlaceholderConfigurer"> <property name="locations" value="classpath*:META-INF/spring/*.properties" /> </bean>
<bean class=Demo>
<property name="someString" value="${simpleValue}" />
</bean>
</beans>
context.xml:
<Resource name="email/session/myEmailSession"
type="javax.mail.Session"
auth="Container"
password="secret"
mail.debug="false"
mail.transport.protocol="smtp"
mail.smtp.auth="true"
mail.smtp.user="test#example.com"
mail.smtp.host="mail.example.com"
mail.smtp.from="test#example.com"/>
<Parameter name="simpleValue" value="any" override="false" />

Related

Liferay 7 MessageListener osgi module

When I worked with the liferay 6.1 I created an application that received the message.
Java class:
public class MailMessageBus implements MessageListener
\src\main\webapp\WEB-INF\src\META-INF\messaging-spring.xml file:
<beans
default-destroy-method="destroy"
default-init-method="afterPropertiesSet"
xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
<!-- Root Context: defines shared resources visible to all other web components -->
<bean id="messagingConfigurator" class="com.liferay.portal.kernel.messaging.config.PluginMessagingConfigurator">
<property name="messageListeners">
<map key-type="java.lang.String" value-type="java.util.List">
<entry key="mail-send-message">
<list value-type="com.liferay.portal.kernel.messaging.MessageListener">
<ref bean="messageListener.mail_listener" />
</list>
</entry>
</map>
</property>
<property name="destinations">
<list>
<ref bean="destination.mail"/>
</list>
</property>
</bean>
<!-- Destination class -->
<bean id="destination.mail" class="com.liferay.portal.kernel.messaging.ParallelDestination">
<property name="name" value="mail-send-message" />
</bean>
<!-- Listener class -->
<bean id="messageListener.mail_listener" class="customportlet.AMessageBusListener.MailMessageBus" />
and \src\main\webapp\WEB-INF\web.xml file:
...
<context-param>
<param-name>portalContextConfigLocation</param-name>
<param-value>/WEB-INF/src/META-INF/messaging-spring.xml</param-value>
</context-param>
...
How can I do the same for liferay 7 in the OSGi module? OSGi module does not have a web.xml file.
Thank you very much!
I'm trying to accomplish the same thing, and based on what I've found so far the web.xml is unnecessary. OSGi modules seem to detect spring configuration automatically, according to this resource:
https://docs.spring.io/spring-osgi/docs/current/reference/html/app-deploy.html
Just put your configuration in xml files located at META-INF/spring

deployerConfigContext.xml has no effect

I tried to get a CAS-server up and running using https://github.com/apereo/cas-overlay-template for a side project (I'm a student), but I have never used maven or spring before.
I'm trying to hook my own IPersonAttributeDao into the CAS-server. However, when I put my deployerConfigContext.xml under src/main/webapp/WEB-INF/, nothing actually changed when I repackaged (using the build script) and deployed to tomcat8. (Yes, I did restart tomcat).
Below the contents of my deployerConfigContent.xml file
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:p="http://www.springframework.org/schema/p"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:sec="http://www.springframework.org/schema/security"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.1.xsd
http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-3.1.xsd">
<bean id="authenticationManager" class="org.jasig.cas.authentication.AuthenticationManagerImpl">
<property name="credentialsToPrincipalResolvers">
<list>
<bean id="primaryPrincipalResolver"
class="org.jasig.cas.authentication.principal.PersonDirectoryPrincipalResolver">
<property name="attributeRepository" ref="attributeRepository"/>
</bean>
<bean class="org.jasig.cas.authentication.principal.UsernamePasswordCredentialsToPrincipalResolver">
<property name="attributeRepository" ref="attributeRepository"/>
</bean>
<bean class="org.jasig.cas.authentication.principal.HttpBasedServiceCredentialsToPrincipalResolver">
<property name="attributeRepository" ref="attributeRepository"/>
</bean>
</list>
</property>
<property name="authenticationHandlers">
<list>
<bean id="primaryAuthenticationHandler"
class="org.jasig.cas.authentication.AcceptUsersAuthenticationHandler">
<property name="users">
<map>
<!-- Login stays the default casuser:Mellon, no idea why -->
<entry key="test" value="1234"/>
</map>
</property>
</bean>
<!-- DO NOT EVER PUT THIS BEAN IN PRODUCTION!!! -->
<bean class="org.jasig.cas.authentication.handler.support.SimpleTestUsernamePasswordAuthenticationHandler"/>
</list>
</property>
</bean>
<!-- <bean id="attributeRepository" class="class.i.am.trying.to.hook.in">
</bean>-->
<!-- This doesn't seem to work -->
<bean id="attributeRepository"
class="org.jasig.services.persondir.support.StubPersonAttributeDao">
<property name="backingMap">
<map>
<entry key="uid" value="uid" />
<entry key="eduPersonAffiliation" value="eduPersonAffiliation" />
<entry key="groupMembership" value="groupMembership" />
</map>
</property>
</bean>
</beans>
What am I missing?
UPDATE:
I reread the documentation (https://apereo.github.io/cas/5.0.x/), and found that deployerConfigContext.xml was supposed to be in resources, and not in webapp/WEB-INF as I found on the internet. I moved it, and now I'm finally getting errors in the log (which means the file is being read).
Error below:
org.springframework.beans.factory.CannotLoadBeanClassException: Cannot find class [org.jasig.cas.authentication.PolicyBasedAuthenticationManager] for bean with name 'authenticationManager' defined in class path resource [deployerConfigContext.xml]
I found a reference to PolicyBasedAuthenticationManager in the docs, but trying that gave the same error (with the other classname ofcourse).
Bean classes of enabled beans must be deployed in bean archives.
A library jar, EJB jar, application client jar or rar archive is a
bean archive if it has a file named beans.xml in the META-INF
directory. The WEB-INF/classes directory of a war is a bean archive if
there is a file named beans.xml in the WEB-INF directory of the war. A
directory in the JVM classpath is a bean archive if it has a file
named beans.xml in the META-INF directory.
One suggestion, if you are using Spring, you can also set #Annotation to define beans.

Spring scopes in embedded web app in Jetty server

I configured Jetty to start web app from spring context, e.i. there are two contexts:
external context which runs Jetty
internal which is run by Spring DispatcherServlet
Here is the definition of external context:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="servletHolder" class="org.eclipse.jetty.servlet.ServletHolder">
<constructor-arg name="name" value="dispatcher"/>
<constructor-arg name="servlet" value="org.springframework.web.servlet.DispatcherServlet"/>
<property name="initParameters">
<map>
<entry key="contextConfigLocation" value="classpath:dispatcher-context.xml"/>
</map>
</property>
<property name="initOrder" value="0"/>
</bean>
<bean id="servletHandler" class="org.eclipse.jetty.servlet.ServletHandler">
<property name="servlets">
<array>
<ref bean="servletHolder"/>
</array>
</property>
<property name="servletMappings">
<list>
<bean class="org.eclipse.jetty.servlet.ServletMapping">
<property name="servletName" value="dispatcher"/>
<property name="pathSpec" value="/*"/>
</bean>
</list>
</property>
</bean>
<bean id="contextHandler" class="org.eclipse.jetty.servlet.ServletContextHandler">
<property name="contextPath" value="/spring"/>
<property name="servletHandler" ref="servletHandler"/>
</bean>
<bean class="org.eclipse.jetty.server.Server" init-method="start" destroy-method="stop">
<constructor-arg name="port" value="9999"/>
<property name="handler" ref="contextHandler"/>
</bean>
</beans>
It refers to dispatcher-context.xml which is "internal".
So far it work fine unless I need to inject beans from external context into controller's beans from internal context.
Is there any way to define bean in outer scope and inject it into controller?
It would be useful in unit-test or using this server as a part of bigger existing app.
The full code is available here: https://github.com/zjor/embedded-jetty/tree/master/spring-mvc-jetty
So far I've found a workaround, I've used a combination of Jersey with Jetty and configured everything via Spring.
Code is available here: https://github.com/zjor/embedded-jetty/tree/master/jersey-jetty

Change hibernate.connection.url from within Spring

I am using Hibernate in combination with Spring. As database I am currently using HSQL, which stores its data in a file (like SQLite). The path to the HSQL file is currently hard-coded in the persistence.xml. How can I access and change this value at runtime, so a user can load and save from/to an arbitrary HSQL file?
persistence.xml:
<persistence xmlns="http://java.sun.com/xml/ns/persistence"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/persistence
http://java.sun.com/xml/ns/persistence/persistence_1_0.xsd"
version="1.0">
<persistence-unit name="something-unit">
<provider>org.hibernate.ejb.HibernatePersistence</provider>
<properties>
<property name="hibernate.connection.driver_class" value="org.hsqldb.jdbcDriver" />
<property name="hibernate.connection.url" value="jdbc:hsqldb:file:~/something-db/somethingdb" />
<property name="hibernate.connection.username" value="sa" />
<property name="hibernate.dialect" value="org.hibernate.dialect.HSQLDialect" />
<property name="hibernate.hbm2ddl.auto" value="update" />
</properties>
</persistence-unit>
</persistence>
Spring applicationContext.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:data="http://www.springframework.org/schema/data/jpa"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-2.5.xsd
http://www.springframework.org/schema/data/jpa
http://www.springframework.org/schema/data/jpa/spring-jpa.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-3.0.xsd">
<!-- Database Setup -->
<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalEntityManagerFactoryBean">
<property name="persistenceUnitName" value="something-unit" />
</bean>
<data:repositories base-package="com.something.playlist"/>
<!-- Transaction Setup -->
<tx:annotation-driven/>
<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="entityManagerFactory"/>
</bean>
</beans>
Thanks for any hint!
You can specify a JNDI datasource and pass it to Hibernate. Or you can define your own plugin strategy for obtaining JDBC connections by implementing the interface org.hibernate.connection.ConnectionProvider
For more hints see: http://docs.jboss.org/hibernate/orm/3.3/reference/en/html/session-configuration.html
Edit 2/16: There is an example on StackOverflow on creating a custom ConnectionProvider: How can I set Datasource when I'm creating Hibernate SessionFactory?
If you are going to change the data source on the fly, rather than at the startup, you will have to restart the Hibernate session factory. To do it correctly, you will have to make sure that no transactions are running in it at the time of the restart. Following question/answers would help you with that: Hibernate Sessionfactory restart | Spring
A commonly used strategy is to define all runtime configurations in one or several *.properties files and use spring's PropertyPlaceholderConfigurer to load the values and substitute the placeholder in applicationContext.xml, read more here: Best ways to deal with properties values in XML file in Spring, Maven and Eclipses.
app.properties:
# Dadabase connection settings:
hibernate.connection.driver_class=org.hsqldb.jdbcDriver
hibernate.connection.url=jdbc:hsqldb:file:~/something-db/somethingdb
hibernate.connection.username=sa
hibernate.connection.password=changeit
hibernate.dialect=org.hibernate.dialect.HSQLDialect
hbm2ddl.auto=update
... ...
applicationContext-dataStore.xml:
<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="locations">
<list>
<!-- Default location inside war file -->
<value>classpath:app.properties</value>
<!-- Environment specific location, a fixed path on deployment server -->
<value>file:///opt/my-app/conf/app.properties</value>
</list>
</property>
<property name="ignoreResourceNotFound" value="true"/>
</bean>
... ...
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="${hibernate.connection.driver_class}" />
<property name="url" value="${hibernate.connection.url}" />
<property name="username" value="${hibernate.connection.username}" />
<property name="password" value="${hibernate.connection.password}" />
</bean>
One problem here is the PropertyPlaceholderConfigurer doesn't parse persistence.xml, the solution is to move all hibernate configuration into Spring's applicationContext.xml, as it is not necessary to set them in persistence.xml. read more here: loading .properties in spring-context.xml and persistence.xml.
persistence.xml:
<?xml version="1.0" encoding="UTF-8"?>
<persistence xmlns="http://java.sun.com/xml/ns/persistence"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_1_0.xsd"
version="1.0">
<persistence-unit name="JPAService" transaction-type="RESOURCE_LOCAL"/>
</persistence>
applicationContext-datSource.xml:
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="${hibernate.connection.driver_class}"/>
<property name="url" value="${hibernate.connection.url}"/>
<property name="username" value="${hibernate.connection.username}"/>
<property name="password" value="${hibernate.connection.password}"/>
</bean>
... ...
<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="persistenceXmlLocation" value="classpath:./META-INF/persistence.xml"/>
<property name="persistenceUnitName" value="JPAService"/>
<property name="dataSource" ref="dataSource"/>
<property name="jpaVendorAdapter">
<bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
<property name="databasePlatform" value="${hibernate.dialect}"/>
<property name="showSql" value="true" />
<property name="generateDdl" value="true"/>
</bean>
</property>
<property name="jpaProperties">
<!-- set extra properties here, e.g. for Hibernate: -->
<props>
<prop key="hibernate.hbm2ddl.auto">${hbm2ddl.auto}</prop>
</props>
</property>
</bean>
Note that the web application need to be restarted every time you alter the configuration in /opt/my-app/conf/app.properties, in order to make changes take effect.
Hope this helps.
If you wish to use hibernate via the JPA Abstraction you can we-write your code or service to use an javax.persistence.EntityManagerFactory. Autowire one of these and call createEntityManager(Map map); You can provide a datasource in the map. You could wrap the entity manager with your own implementation that pulls the parameter off a thread-local for creating the datasource.
EDIT: Mis-read the context and saw you are using an EntityManagerFactory. In which case just read the last part where you wrap the Factory with a delegate that creates the correct datasource from a threadlocal.

Spring Quartz simple trigger not firing as expected

I am having a simple trigger bean which should be fired for every 20min.
For that I am specifying the repeatinterval value in properties file. But my job is getting waked up every minute instead of every 20min.
sample xml
<bean id="propertyLoaderJob"
class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean">
<property name="targetObject" ref="propertyloader" />
<property name="targetMethod" value="propFlagValidator" />
<property name="concurrent" value="false" />
</bean>
<bean id="propertyLoaderTrigger"
class="org.springframework.scheduling.quartz.SimpleTriggerBean">
<property name="jobDetail" ref="propertyLoaderJob" />
<property name="repeatInterval" value="${quartz.scheduler.repeatInterval}" />
<property name="startDelay" value="${quartz.scheduler.startDelay}" />
</bean>
in the properties file I have these fields
quartz.scheduler.repeatInterval=1200000
quartz.scheduler.startDelay=1000
What could be the possbile reason for this?
Please help.
Thanks in advance.
Have you specified a property placeholder for this,
Using Context namespace,
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd">
. . .
<context:property-placeholder location="quartz.scheduler.properties" />
. . .
</beans>
or Adding PropertyPlaceholderConfigurer bean in application context
<bean id="propertyConfigurer" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="location">
<value>classpath:quartz.scheduler.properties</value>
</property>
</bean>
Are you sure that you are not using any other trigger for the same class/job i.e. propertyLoaderJob. It may have happened that you are using a cron expression as well associated with the same job. It will be great if you can share the complete spring xml file.
For future reference i am answering.
Along with the mentioned part in my question i forgot to add the below code. That is for actually triggering it:
<bean name="nonclusterMode" class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
<property name="triggers">
<list>
<ref bean="propertyLoaderTrigger" />
</list>
</property>
</bean>
Now it is working as expected.

Resources