I am new to openJPA.
I have a scenario where, depending upon the server where my application is running, I need to change the settings to persistance.xml.
For eg. if its running on Server A, then it should use different database(different url), different password etc. and if the application is running on Server B then it should use different information.
And could you also tell me, which way should it be done, using datasource or simply putting properties under persistence-unit.
FYI I am using WS app. server 7 and RAD 7.5
Any type of help would be highly appreciated.
You're using an application server so you don't need to set database connection settings in the persistence.xml file. You should be able to create a JNDI data source in your appserver and then use that. EAch server could have the data source have the same JNDI name and then there'll be no need for any persistence.xml differences.
Workshop, JPA, and DataSources seems particularly relevant to you. As does Setting up a JNDI data source in WebSphere 6.0/6.1 and WebSphere + JNDI + Spring Framework + Hibernate.
Are you using Spring? If so, then the problem is easy to solve: you don't put the data source information in your persistence.xml, you put it in your application context and that'll have different configuration on each server.
For example:
<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="location" value="classpath:database.properties"/>
</bean>
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
<property name="driverClassName" value="${database.class}"/>
<property name="url" value="${database.url}"/>
<property name="username" value="${database.username}"/>
<property name="password" value="${database.password}"/>
</bean>
and each server could have a different database.properties file on each server (where each is in the classpath somewhere in this example):
database.username=scratch
database.password=scratch
database.class=oracle.jdbc.OracleDriver
database.url=jdbc:oracle:thin:#localhost:1521:XE
Changing persistence.xml at runtime is going to be problematic as that's not really how JPA is designed.
Of course, you can use JNDI data sources with Spring also.
Related
I have recently started deploying my web applications into Google cloud platform. Fortunately, I've solved every annoying errors, exceptions, troubles on my own by researching in stack overflow and other platforms. My current deployed application establish the connection to my real oracle database which is located in Oracle Cloud Infrastructure. While running my web app in localhost, of course it connects because the config file points to wallet folder in my file system. But now in cloud, I don't know where to store my wallet to reference it from my hibernate config xml. And also I don't know if it's possible to reference somewhere other than filesystem, like https://blablafileupload.com/mywalletfolder.
I'm gonna provide my config file below. Can you help me if you know how to do it, and also where is the best place for storing such database wallets (I guess the storage in the location same as my deployment is good place, but I don't know how).
-<bean class="com.mchange.v2.c3p0.ComboPooledDataSource" destroy-method="close" id="myDataSource">
<property value="oracle.jdbc.driver.OracleDriver" name="driverClass"/>
<property value="jdbc:oracle:thin:#oraclesql_medium?TNS_ADMIN=/Users/user/Desktop/Fuad/Wallet_OracleSQL/" name="jdbcUrl"/>
<property value="TABLE" name="user"/>
<property value="********" name="password"/>
<!-- these are connection pool properties for C3P0 -->
<property value="5" name="minPoolSize"/>
<property value="20" name="maxPoolSize"/>
<property value="30000" name="maxIdleTime"/>
</bean>
As you can see on 3rd line, it refers to the wallet folder in my filesystem ( I want to store that somewhere and make xml refers to it on Internet.)
I am writing a Spring Jar (Without Spring boot) which connects to database. Almost all the tutorials which I saw connects to Database using the spring XML and the password is hard coded in the XML file.
This is in no way allowed in production environment and way out of standards in terms of security.
Can someone please help me if there is a way to inject password from a method call which inturn retrieves the password from a secured vault and provides the password to datasource object in runtime.
something like below.
<bean id="dataSource" class="org.springframework.jdbc.datasource.SingleConnectionDataSource">
<property name="driverClassName" value="org.postgresql.Driver" />
<property name="url" value="jdbc:postgresql://localhost:5432/postgres" />
<property name="username" value="postgres" />
<property name="password" value=getPasswordfromSecureVault("username") />
<property name="suppressClose" value="true" />
<jdbc:initialize-database >
<jdbc:script location="create-tables.sql"/>
</jdbc:initialize-database>
Based on the spring boot tag that you have, I'll assume that you're using spring boot for your project. With spring boot, it is very easy to externalize configuration for your application. It also auto-configures your datasource with a connection pool if you use the starters they provide.
In your case, you could benefit from moving to using spring boot's Externalized Configuration.
What that would allow you to do is to use an environment variable to configure your spring application. For example, to configure your password, use the environment variable SPRING_DATASOURCE_PASSWORD. You could also use the Java option -Dspring.datasource.password=[password] when starting the application, for example:
java -jar -Dspring.datasource.password=password app.jar
If using docker containers, the environment variable way is generally my go to as it's very straight forward for people to understand.
If you really want to configure the password from a method call, you can do that too using java configuration. Create a bean of type DataSource and Spring should pick it up and use it.
#Configuration
class AppConfiguration {
#Bean
public DataSource dataSource() {
String password = // Get your password
return DataSourceBuilder.create().password(password).build();
}
}
I've got a Spring Integration flow which uses an inbound gateway to get messages from an IBM MQ queue:
<int-jms:inbound-gateway id="InputGateway"
request-destination="RequestQueue"
request-channel="RequestChannel"
reply-channel="ReplyChannel"
/>
However I'm not capable of assigning security settings. In particular, I need an username, password and userAuthenticationMQCSP = false (for reasons beyond the scope of this post, I won't get into details but my broker will throw a MQRC = 2009 otherwise).
I've followed the IBM guide to connect with jmsTemplate and works just fine. This uses the official Spring boot starter from IBM MQ which will kindly create a connection factory and will autoconfigure it with some defaults from application.properties:
ibm.mq.queueManager=myQMName
ibm.mq.channel=myChannel
ibm.mq.connName=myhostname(myPort)
ibm.mq.user=username
ibm.mq.password=*******
ibm.mq.userAuthenticationMQCSP=false
Now, back to the Spring Integration case. According to the int-jms:inbound-gateway spec, a connectionFactory will be injected to the gateway, by name (attribute: connection-factory) which is set up to be "jmsConnectionFactory" by default
By default, all of the JMS adapters that require a reference to the
ConnectionFactory automatically look for a bean named
jmsConnectionFactory. That is why you do not see a connection-factory
attribute in many of the examples. However, if your JMS
ConnectionFactory has a different bean name, you need to provide that
attribute.
I don't see any way to set up a predictable name for the connection factory that I can plug into the int-jms:inbound-gateway.
Now, taking a different approach, as per this example I've created my connectionFactory with an adecuate name:
<bean id="jmsConnectionFactory" class="com.ibm.mq.jms.MQQueueConnectionFactory">
<property name="transportType" value="1"/>
<property name="queueManager" value="myQMName"/>
<property name="hostName" value="myhostname"/>
<property name="port" value="myPort" />
<property name="channel" value="myChannel"/>
</bean>
But now I need somewhere to put the credentials and the security parameters. Looking at the example above, it looks like I need to plug something like:
<bean id="secureJmsConnectionAdapter" class="**yourpackages.SecureJMSConnectionAdapter**">
<property name="targetConnectionFactory" ref="${jms.mq.connection.factory}" />
<property name="userName" value="${jms.username}"/>
<property name="pwdAlias" value="${jms.alias}"/>
</bean>
However it is unclear to me how to implement this SecureJMSConnectionAdapter.
Additionally, if I set up my own connection factory, I will lose all of MQ boot starter automagic thanks to this annotation on the MQAutoConfiguration class:
#ConditionalOnMissingBean(value=javax.jms.ConnectionFactory.class)
Any ideas on how to put these pieces together?
EDIT: Just to avoid any possible red herrings to anyone, the MQRC2009 was irrelevant to ibm.mq.userAuthenticationMQCSP=false.
Some of my old projects I used a bean like this:
<bean id="jmsQueueConnectionFactory"
class="org.springframework.jms.connection.UserCredentialsConnectionFactoryAdapter">
<property name="targetConnectionFactory" ref="jmsConnectionFactory"/>
<property name="username" value="${jms.username}"/>
<property name="password" value="${jms.alias}"/>
</bean>
Should work well as a wrapper for your com.ibm.mq.jms.MQQueueConnectionFactory, but you have to use this jmsQueueConnectionFactory in the target components.
Although it looks like the mentioned IBM MQ JMS Spring doesn't that for us properly exposing a jmsConnectionFactory bean. You can rely on the default from Spring Integration in this case or use that jmsConnectionFactory explicitly for the connection-factory.
Also with Spring Boot you should consider to go away from XML configuration and give a chance for Spring Integration Java DSL: https://docs.spring.io/spring-integration/docs/5.1.7.RELEASE/reference/html/#java-dsl
I have a java based web application deployed on Tomcat 6. I need to make some properties as configurable. Currently i have created a config.properties file and load that file in a static Properties object.
I want to know if there is any other efficient method or framework to use configurable properties in Java web applications?
Try this sample;
This is sample Resource.properties file that place in com.package;
name=John
email=john#company.com
description=John is a Java software developer
And access likes this;
private static final String PROPERTIES_FILE = "com/package/Resource.properties";
Properties properties = new Properties();
properties.load(this.getClass().getResourceAsStream(PROPERTIES_FILE));
String name = props.getProperty("name");
String email = props.getProperty("email");
String description = props.getProperty("description");
The other framework to use configurable properties is JSF.This sample is the usages of properties in JSF.
Another option you might have would be to have one class with all your constants of your projects defined in it. This will provide you with a centralized way in which you can configure your application effectively and efficiently.
That being said however, I think that using the configuration files is the best option since (I do not think) that you would have to recompile your code each time after changing.
EDIT: Seeing some of the comments above, what you could make would be to have a separate table in your database in which you would be able to store all your constants. You can then make this table available to system administrators and other support personnel through a back end web interface.
The enterprise level answer would be to load your configuration through an integration framework like Spring. If your application is fairly small I wouldn't necessarily recommend it, though.
Loading properties with Spring Framework:
<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-3.0.xsd">
<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="location" value="classpath:configuration.properties"></property>
</bean>
<!-- Here is configutaion for connection pool -->
<!-- Those ${} properties are from the configuration.properties file -->
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource">
<property name="driverClassName" value="${db.driver}"/>
<property name="url" value="${db.url}"/>
<property name="username" value="${db.user}"/>
<property name="password" value="${db.pass}"/>
</bean>
</beans>
I have a Java web-app using standard web.xml and servlets. At the moment, I'm using the <context-param> tags in web.xml to define the database configuration (JDBC url, username, password, etc.). These are picked up by a servlet in its init() method.
But I'd like to not include database username/password in my source repository.
For testing, I'm using jetty-maven-plugin. With that, I specify an option overrideDescriptor with a supplementary web.xml that is applied after the primary web.xml. I put my testing database configuration in this supplementary file, and everything works great.
For deployment, my host is using Tomcat. I'm not sure how to apply a database config here. Is there a similar way to specify a supplementary web.xml file? If not, what is the best practice to do this? Read the configuration from a separate properties file (or similar) included as a resource?
You should be using connection pools and JNDI. You keep the credentials on the server that way. Users only need the JNDI lookup name (e.g., "jdbc/FooDataSource") to access the connection pool.
"Read the configuration from a separate properties file (or similar) included as a resource?"
Yes.
There are lots of ways to do THAT, too. My current project uses Spring's PropertyPlaceholderConfigurer to read the appropriate properties files and allow any of the values to be used in a context file using the usual ${whatever} notation.
Addition:
Incidentally, we use a custom subclass of PropertyPlaceholderConfigurer to set the locations of the files. We use a "global" properties file that applies to all environments (dev, test, uat, prod) and then one file for each environment that overrides the global settings.
The files themselves are deployed in a jar, but we don't need the flexibility of changing the values on the fly.
You could always store the configuration in an external .properties file, change your servlet to read from this instead (perhaps having web.xml point at the path to the file), and thus keep the file only on the server and out of source control.
In your application-context.xml , you can use the place holders and point the location of the placeholder's parameters to external properties file.
<bean id="propertyConfigurer"
class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="location">
<value>/WEB-INF/database-config.properties</value>
</property>
</bean>
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
<property name="driverClassName" value="${jdbc.driver}"/>
<property name="url" value="${jdbc.url}"/>
<property name="username" value="${jdbc.user}"/>
<property name="password" value="${jdbc.password}"/>
</bean>
In your database-config.properties file. You can provide the placeholder's parameters. In this case database settings.
jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/school?useUnicode=true&characterEncoding=UTF-8
jdbc.user=root
jdbc.password=root