I need some help with the Context.xml file in my Java Web Application in Netbeans.
My task was to get my Web App to connect to and display products from my SQL database. I got it to work but I really need help understanding this code:
<Resource auth="Container" driverClassName="com.mysql.jdbc.Driver"logAbandoned="true" maxActive="100" maxIdle="30" maxWait="10000" name="jdbc/project" password="" removeAbandoned="true" removeAbandonedTimeout="60" type="javax.sql.DataSource" url="jdbc:mysql://localhost:3306/projinvoice?zeroDateTimeBehavior=convertToNull" username="root"/>
Could anyone tell me what name="jdbc/project" is? Where does this link to?
If I change the name then the Web App does not display my products. How did it get set to jdbc/project and where can I find it?
I did try and use Glassfish to create a JDBC Resource where I could have used that name but it does not show up?
Any help would be appreciated.
Regards
Context.xml is a configuration file for the container. Glassfish and Tomcat for example are using this file.
It declaratively configures the DataSource object in this case. At startup of the web-application, the container will instantiate this object and exposes it through JNDI.
JNDI is a mechanism to look for objects in the VM by name.
So somewhere on your web-app classes, this name is used to fetch this DataSource object. Have a search!
Related
Hoping that someone can clear up a few things -
For a project I need to be able to switch between a Sybase and an Oracle database. Using Spring I have been to come up with a solution using AbstractRoutingDataSource to allow switching between the sybase and oracle data source as needed.
However, within my tomcat context.xml, I have listed all data sources - so for each one I have "jdbc/myDbSybaseDataSource" and "jdbc/myDbOracleDataSource". I was wondering, does tomcat attempt to create all of these data sources on start up, or does it wait until something in the code has invoked it?
I know in spring you can lazy load your beans, but would tomcat still create each resource in the context.xml anyways?
Any help is much appreciated!
Edit
The reason for asking is - if for example, the Sybase database is down, we need to know that we can switch to the Oracle, but Tomcat will not try and load the Sybase resource from the context.xml at start up (unfortunately I am not in a position to turn off one of the databases to test this! :) ).
From what I can tell, Tomcat is loading the resources - but not trying to actually connect to the database until part of the code invokes the data source, at which point Spring kicks in and does its work. It simply loads in the resources and keeps the info stored somewhere, when Spring tries to create the data source it looks up the corresponding resource info and uses this
Yes, Tomcat will create these datasources at startup. I cannot tell you how far this initialization goes but I would try to avoid any overhead that you dont need.
Do you need both datasources at runtime or is it just to be able to decide at startup of your application?
In the second case you can see the cotext.xml file as an (external) configuration file. You can then use springs jndi reference feature to connect to the desired database for the current application.
In the root-context.xml you reference ONE datasource by name:
<jee:jndi-lookup id="mvcDatasource" jndi-name="jdbc/mvcDatasource"
expected-type="javax.sql.DataSource" />
And depending on which type should be used you declare the correct implementation in the context.xml:
<Context>
<Environment name="configDirectory" type="java.lang.String" value="file:///tmp/app1" />
<Resource name="jdbc/mvcDatasource" type="javax.sql.DataSource" auth="Container" driverClassName="org.h2.Driver" maxActive="8" maxIdle="4" username="user" password="" url="jdbc:h2:file:/tmp/app1/db" />
</Context>
As you can see you can use other declarations too. In my case i inject the external config location here to be able to load properties files for the propertyconfigurer too. So this location will be application specific.
i want to migrate my applicaztion in aws,
i have setup my env. using elastic beanstalk.
in current version of my application, it runs OK locally, i setup the connection with this simple code:
in web.xml i have defined the resource:
<resource-ref>
<description> Resource reference to a factory for java.sql.Connection instances that may be used for talking to a particular database that is configured in the <Context> configuration for the web application. </description>
<res-ref-name>jdbc/TestDB</res-ref-name>
<res-type>javax.sql.DataSource</res-type>
<res-auth>Container</res-auth>
</resource-ref>
then in config.xml i defined the resource
<Resource name="jdbc/TestDB" auth="Container" type="javax.sql.DataSource" maxActive="100" maxIdle="30" maxWait="10000" username="utente1" password="utente1" driverClassName="com.mysql.jdbc.Driver" url="jdbc:mysql://localhost:3306/nazioni?autoReconnect=true" />
now i'm able to get the connection in this way
/* JNDI query to locate the DataSource object */
Context initContext = new InitialContext();
Context envContext = (Context)initContext.lookup("java:/comp/env") ;
// JNDI standard naming root
DataSource ds = (DataSource)envContext.lookup("jdbc/TestDB");
/* Ask DataSource for a connection */
Connection conn = ds.getConnection();
now my question is: can i hard code the connection string in my config.xml or it is better to use System.getProperty("JDBC_CONNECTION_STRING")? if so, how i can set the connection string when tomcat is loaded ?
thanks, Loris
Tomcat Configuration Reference mentioning support for Ant-style variable substitution:
Apache Ant-style variable substitution is supported; a system property
with the name propname may be used in a configuration file using the
syntax ${propname}. All system properties are available including
those set using the -D syntax, those automatically made available by
the JVM and those configured in the
$CATALINA_BASE/conf/catalina.properties file.
It means that if you define a property within .ebextensions/<environment-name>.config such as:
option_settings:
- option_name: JDBC_CONNECTION_STRING
value: jdbc:mysql://localhost:3306/nazioni?autoReconnect=true
Then you should be able to reference that property in the configuration files:
<Resource name="jdbc/TestDB" auth="Container" type="javax.sql.DataSource" maxActive="100" maxIdle="30" maxWait="10000" username="utente1" password="utente1" driverClassName="com.mysql.jdbc.Driver" url="{JDBC_CONNECTION_STRING}" />
The approach has at least two benefits over hardcoded:
The value can be changed manually in AWS Beanstalk Console on a running instance
The value can be changed programmatically on a running instance
Better go with XML configuration Becasue most of the application when moved from one Environment to another.There will be change in XML probably so XML is better from my Experience.
Also you can use property file but which helps most of the time when you want some property which is to be changed very often like lables not like configuration based things DB Connection String,SMTP,etc.
The Name of WEB.XML is Deployment descriptor becasue at the time deployment which is useful to load details about Applications based on the different environment.
In general, it is best NOT to hard-code connection string information within your application (or other similar application configuration). Ideally you want to externalize application configuration so that your application to be portable between environments.
In the case of Elastic Beanstalk, you could deploy the same application WAR in different Beanstalk environments at the same time (perhaps a QA and a PROD environment) and if you hard-code the connection string then both WAR files would be pointing to the same DB instance.
Similarly, you may need to change the connection string at some point, maybe because your DB instance name changed, and if you hard-code the connection string then you would have to rebuild and deploy a new JAR.
If you use the JDBC_CONNECTION_STRING configuration provided by Elastic Beanstalk and read these in at runtime, then you can easily change the connection string using the Elastic Beanstalk console or API, and you can also maintain portability for a single WAR between different environments.
I have a war file in which a class calls a MySQL DB from Java and thus has the MySQL login information in plain text in the source code. Obviously, for security resons, I don't want this visible to the outside world. The question is thus if the source code in a war file deployed on Tomcat is visible to the outside world?
It's not a problem but not flexible. More usefull to use JNDI. In context.xml put something like this:
<Resource
name="jndi_name_for_datasource"
auth="Container"
type="javax.sql.DataSource"
factory="org.apache.tomcat.jdbc.pool.DataSourceFactory"
testOnReturn="true"
validationQuery="select 1 from dual"
timeBetweenEvictionRunsMillis="30000"
minIdle="1"
initialSize="1"
minEvictableIdleTimeMillis="30000"
username="solaris"
password="super"
driverClassName="oracle.jdbc.driver.OracleDriver"
url="jdbc:oracle:thin:#localhost:1521:slife"
/>
and use lookup fo JNDI name
No it wont be visible. Provided there is no way to download war- Once war is downloaded- Anyone can locate the class and decompile it to see the password.
Better option would be to configure DataSoure - which is outside of your war.
But I think it is still a security issue, if anybody else is having access to tomcat server. e.g. other employees or administrators.
I would suggest you to add simple encryption/decryption technique in the code to prevent others to figure out the password.
what is benefit of defining db pool in tomcat vs in spring configuring file
<Resource name="jdbc/DBCPosPool" auth="Container" type="javax.sql.DataSource"
maxActive="30" maxIdle="10" maxWait="10000"
validationQuery="SELECT 1"
testOnBorrow="true"
username="xxx" password="xxx" driverClassName="com.mysql.jdbc.Driver"
url="jdbc:mysql://abcd.com/test2?autoReconnect=true"/>
I can think of 3 benefits.
Your datasource can be reused by other web applications
Your datasource can be administered externally, independant from the web application. You never want to re-deploy code if the datasource changes. In big organisations the developer is usually not the person who administers the datasources and stuff.
Environment specific details. It's possible that you're working in a DTAP environments or something similar. The datasource can be different depending on your environment (development, production, ...). You don't want to maintain seperate Spring configuration files just for the sake of the data connection.
Defining pool in tomcat allows you to reuse this definition in others, non spring apps. Defining it in spring level helps you to deploy yor app including other containers.
If your application is packaged to a war file, defining resources in an application server allows you to modify the resources without rebuilding the application. All you need is to restart the application server. This is useful when deploying the same application on different environments (dev, test, prod etc).
I am using Tomcat's 7 connection pool. My configuration is the following:
In server.xml:
<GlobalNamingResources>
<!-- Editable user database that can also be used by
UserDatabaseRealm to authenticate users
-->
<Resource name="jdbc_DS" auth="Container"
type="javax.sql.DataSource"
factory="org.apache.tomcat.jdbc.pool.DataSourceFactory"
driverClassName="org.h2.Driver"
url="jdbc:h2:file:absolutePathtodatabase"
username="root" password=""
maxActive="20" maxIdle="10" maxWait="-1"
/>
</GlobalNamingResources>
And in context.xml:
<ResourceLink name="jdbc/myDS"
global="jdbc_DS"
type="javax.sql.DataSource"/>
It seems to work but I noticed the following:
In the attributes of resource here:global resources it doesn't mention factory as attribute of a Resource.Nevertheless I have defined it in server.xmland got no error.
What does this mean?Am I not using a org.apache.tomcat.jdbc.pool.DataSourceFactory factory here?
But you aren't using a <Resource> in context.xml, you are using a <ResourceLink>, so whatever attributes a <Resource> may have in context.xml is irrelevant. The <ResourceLink> just has enough attributes to refer to the <Resource>, which is fully defined elsewhere, including its factory attribute.
The Tomcat 7 documentation tells us, that you're configuration is correct for using a data source factory:
The Tomcat Connection pool is configured as a resource described in The Tomcat JDBC documentation With the only difference being that you have to specify the factory attribute and set the value to org.apache.tomcat.jdbc.pool.DataSourceFactory
The documentation further mentions:
You MUST also define any other needed parameters using attributes on the Resource element, to configure the object factory to be used (if not known to Tomcat already), and the properties used to configure that object factory.
which is another hint, that the list of valid elements is not complete.