Properties in Spring, accessing within Java app - java

I have a properties set like so :
<context:property-placeholder
location="file:${catalina.home}/conf/my.properties"
ignore-unresolvable="true" />
they are then referenced in app context (specifically app.email) like so :
<bean id="alertMailMessage" class="org.springframework.mail.SimpleMailMessage">
<property name="to">
<value>${app.email}</value>
</property>
</bean>
However when I try to access that property within an actual pojo, not a spring bean - actually a pojo annotated as a hibernate entity (not the alertMailMessage bean) it is coming back as null ?
#Value("${app.email}")
private String defaultEmailAddress;
I want to use the value of property setting "app.email" elsewhere, other than alertMailMessage, whats the best way ? (alertMailMessage is working fine btw)

You can't set it in a hibernate entity, because hibernate entities are not managed by spring.
Use the #Value annotation in your spring service which creates the hibernate entity, and set it manually if needed. But it looks odd to store a default value in the database, so reconsider that.
As a sidenote: you can have hibernate entities managed by spring if using aspectJ and #Configurable, but that may complicate things unnecessarily.

Related

Suggestion to implement custom bean initialization/creation logic in Spring

In my Java/spring project there are lots of beans configured in an xml like,
<beans>..
<bean id="beanOne" class=...>
<property name="x" value="1"/>
<property name="y" value="something"/>
<property name="z" value="something else"/>
</bean>
</beans>
"beanOne"'s properties(x,y,z) values keep changing for different needs/machines. I can create different xml files having different values, one for each need/machine. But I want to write some custom bean creation logic so that I can define different properties in a single properties (or) json file and the custom class takes care of creating the beans with appropriate values from that single properties (or) json file for all needs/machines.
So how to can I do that in spring? - Extend AbstractFactoryBean, implement FactoryBean, implement BeanFactory, or something else? I just need the logic/skeleton of how to do that using spring.
Follow these steps to do the same,
create the object for your required bean.
Set the required properties for that object, you can fetch it from anywhere you want.
Register that object in beanFactory as a bean.
Reference : https://wordpress.com/post/anilagrawal038.wordpress.com/3

How to configure Spring property at runtime

For this bean :
<bean id="myBean"class="com.MyBean">
<property name="test" value="mytest"/>
</bean>
What is an approprate method of update the property value at runtime ?
I've read about Lookup method injection : http://docs.spring.io/spring/docs/3.0.0.M3/reference/html/ch04s03.html#beans-factory-method-injection
But I don't think this is suited to this scenario as I want to change the value of a property not re-instantiate a Spring managed bean, but perhaps this is the same thing in Spring ?

How to inject all properties from Spring into a bean?

I want to inject a map containing all the properties that spring knows of (which are inserted by a library) to a config class that I have through the spring xml. Is that possible?
<bean class="Config">
<constructor-arg name="env">
<map>
//inject all properties?
</map>
</constructor-arg>
</bean>
Why don't you just inject the Spring Context? Through the Context, you can look up any bean via its name.
Edit:
From this answer, you could also use the following:
<bean class="Config">
<constructor-arg name="env">
<util:properties location="${path.to.properties.file}"/>
</constructor-arg>
</bean>
Where your "env" constructor argument is a java.util.Properties object.
For later versions of Spring (including spring-boot) that support the injection of an Environment you can use this to access all properties loaded.
To answer this question inject a AbstractEnvironment so that you are able to call the getPropertySources() method that will allow you to see where the properties have been loaded from (e.g. a file, OS variables, etc)
#Autowired
public Config(AbstractEnvironment environment)
{
MutablePropertySources propertySources = environment.getPropertySources();
// inspect propertySources to see all properties loaded by Spring
}
Can you not extend the library class that you use and instantiate your bean instead of the default library one? Then you would be able to inspect all the values.
Otherwise, if you know the signature of the library, you can always use AOP to weave some code around the library and get access to the properties there. A bit more complicated, but still gets you where you need to go. You can definitely use AspectJ (which requires a little more config) or even Spring AOP, depending how things are being accessed.
If you want/need more insight on this, let me know.

How to enable multi-tenancy in Hibernate 4 with JPA?

It looks to me as though support for multi tenancy has been added to hibernate for nearly six months now and updated at least once since.
It looks fairly trivial to obtain a multi-tenant Session outside of JPA:
Session session = sessionFactory.withOptions().tenantIdentifier( "jboss" ).openSession();
But how would you enable it in an application that uses hibernate via JPA? (If possible).
Thanks in advance.
You can configure it via properties in persistence.xml as follows:
<property name="hibernate.multiTenancy" value="DATABASE"/>
<property name="hibernate.multi_tenant_connection_provider" value="com.example.MyConnectionProvider" />
<property name="hibernate.tenant_identifier_resolver" value="com.example.MyTenantIdResolver" />
If you use SCHEMA as multi-tenancy strategy hibernate.multi_tenant_connection_provider is not needed.
You can also set these properties in your code and pass them in a map to Persistence.createEntityManagerFactory(). In this case you can pass an object instance, not just a class name.
More info in Hibernate documentation.
EntityManager.getDelegate() will return underlying SessionImpl.

Why I have to declare each and every class in my hibernate.cfg.xml when using annotations?

Why it isn't enough to set the #Entity annotation?
Am I missing the point here e.g. performance?
The annotation is not enough because hibernate does not know where your annotated classes live without some sort of explicit declaration. It could, in theory, scan every single class in the classpath and look for the annotation but this would be very very expensive for larger projects.
You can use spring which has a helper that can allow you to specify the package(s) that your hibernate objects are in and it will just scan these packages for #Entity. If you have all your objects in a small number of fixed packages this works well.
E.g.
<bean id="referenceSessionFactory" class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">
<property name="dataSource" ref="dataSource"/>
<property name="packagesToScan">
<array>
<value>com.xxx.hibernate.objects</value>
</array>
</property>
</bean>
The above is the Spring declaration. If you aren't familiar with the above syntax you can just construct it programmatically.
AnnotationSessionFactoryBean sfb = new AnnotationSessionFactoryBean();
sfb.setDataSource( ds );
sfb.setHibernateProperties( hibProps);
sfb.setPackagesToScan( ... );
sfb.initialise();
SessionFactory sf = sfb.getObject();
It supports a bunch of config options so you can use raw properties or pass in a pre-config'd datasource.
You don't if you set hibernate.archive.autodetection property to true. There is a performance issue here as Hibernate will search the jar files for the JPA annotation. Note that, it will also initializes those classes.
Yes :)
The hibernate.cfg.xml file is not used to specify your entities, it's used to configure things like hibernate's connection parameters and global settings. The hibernate.cfg.xml file also contains instructions on how to locate the entities. You can list the XML mapping files using <mapping resource=XYZ>, but if you're using JPA annotations like #Entity, then this is unnecessary, Hibernate will auto-detect them.
You can mix annotations and mapping XML if you choose, but that's by no means necessary in most situations.
By default all properly annotated
classes and all hbm.xml files found
inside the archive are added to the
persistence unit configuration. You
can add some external entity through
the class element though.
Hibernate EntityManager Reference Docs

Categories

Resources