I'm trying to run an existing WebSphere application in Liberty Profile but have run into a problem. The application has a resource environment entry configured in the server which I need to translate into a Liberty Profile resource. How can I configure a JNDI resource in the server.xml, that isn't a datasource (dataSource) or a constant (jndiEntry)?
Many thanks
You can configure this using the element in the server.xml. This is documented in the infocenter. Essentially you enable the jndi feature in the server.xml using this:
<featureManager>
<feature>jndi-1.0</feature>
</featureManager>
Then you can configure the JNDI entries. You can only do simple types using this, so no complex objects. To configure your entry you then do this:
<jndiEntry jndiName="myProp/philosopher" value="plato" />
The Liberty profile does type inference, so if you expressed this:
<jndiEntry jndiName="myProp/philosopher" value="1234" />
you get an Number from JNDI. If you express this:
<jndiEntry jndiName="myProp/philosopher" value="1234.3D" />
You get a Double.
If you want a number as a string literal you would express it using quotes:
<jndiEntry jndiName="myProp/philosopher" value='"1234.3D"' />
To get this from your application you can do a global lookup such as:
Context ctx = new InitialContext();
Object jndiConstant = ctx.lookup("myProp/philosopher");
String philosopher = (String) jndiConstant;
You can also map this to a resource environment entry in the ibm-web-bnd.xml file:
<env-entry name="philosopher" binding-name="myProp/philosopher" />
and then use this code to look it up:
Context ctx = new InitialContext();
Object jndiConstant = ctx.lookup("java:comp/env/philosopher");
String philosopher = (String) jndiConstant;
Currently this is not possible with Liberty Profile. This question was answered in the IBM WasDev forum here https://developer.ibm.com/answers/questions/6221/resource-environment-entries-in-liberty-profile/?community=wasdev
A RFE process (31525) has been created for it to support it in a future release.
In 8.5.5.x there are several new entries:
For example: To configure an URL you can use the jndiURLEntry
Related
When deploying "regular" web apps to Liberty, I was used to binding the global datasource configured in Liberty's server.xml to the individual application by using a child element within the element, like this:
<application context-root="helloApp" location="..." name="helloApp" type="war">
<application-bnd>
<data-source id="db2appDs" name="jdbc/datasource" binding-name="jdbc/theDB"/>
</application-bnd>
...
</application>
<dataSource id="db2ds" jndiName="jdbc/theDB" type="javax.sql.DataSource">
...
</dataSource>
When configuring my first Spring Boot application to deploy to Liberty, I am trying to use the new <springBootApplication> element for it - but I don't seem to be able to add a binding for the datasource I want to use the same way, as this element doesn't seem to support such a child. (It seems to want only <classloader> as a child).
I've seen people suggest I use an #Resource annotation that includes both application-local JDNI name and global JNDI name for the datasorce - but that defeats the purpose, since I don't want to know what the global name is until deploy time.
Is there another way to do this, like we used to before? Or are applications deployed through <springBootApplication> expected to know the global JNDI name of the datasource(s) they want?
Application-defined datasources are not supported for <springBootApplication/>’s. While your application may certainly access a Liberty datasource using its global JNDI name, you should configure the spring.datasource.jndi-name property within your Spring Boot application as described in section 29.1.3 of the Spring Boot features reference. For your example try spring.datasource.jndi-name=jdbc/theDB.
I am trying to add ActiveMQ as a JMS Provider in Websphere Application Server.
I have followed the instructions described here ActiveMQ 5.11 with WebSphere Application Server 8.5 and adapted to the topic.
Unfortunately I am not sure what I need to add in External JNDI name for both Topic Connection Factory and Topic definitions.
As per IBM documentation:
"External JNDI Name The JNDI name that is used to bind the queue into
the application server name space.
As a convention, use the fully qualified JNDI name; for example, in
the form jms/Name, where Name is the logical name of the resource.
This name is used to link the platform binding information. The
binding associates the resources defined by the deployment descriptor
of the module to the actual (physical) resources bound into JNDI by
the platform."
From my understanding this should be the name that I am using in my app to access the resource defined in WAS.
I also have added the resources in my deployment descriptor as resources.
Any help would be highly appreciated.
Regards
Given that you are accessing the resources via resource references (defined in your deployment descriptor), the configured JNDI name should match the lookup name that is defined in your resource reference.
For example, if your resource reference looks like this,
<resource-ref>
<res-ref-name>java:comp/env/jms/topicConnectionFactoryRef</res-ref-name>
<res-type>javax.jms.TopicConnectionFactory</res-type>
<lookup-name>jms/myTopicConnectionFactory</lookup-name>
</resource-ref>
or if your resource-ref lacks lookup-name and you instead have a ibm-web-bnd.xml file with a binding-name,
<resource-ref name="java:comp/env/jms/topicConnectionFactoryRef"
binding-name="jms/myTopicConnectionFactory">
</resource-ref>
then specify jms/myTopicConnectionFactory as the JNDI name.
Application code will then be able to do:
TopicConnectionFactory tcf = InitialContext.doLookup("java:comp/env/jms/topicConnectionFactoryRef");
Application code could also perform a direct lookup of the JNDI name as follows (although using the resource reference is preferred because it is more spec compliant and standard across app servers),
TopicConnectionFactory tcf = InitialContext.doLookup("jms/myTopicConnectionFactory");
The same applies to javax.jms.Topic.
If your resource environment reference in your deployment descriptor looks like this,
<resource-env-ref>
<resource-env-ref-name>java:comp/env/jms/topicRef</resource-env-ref-name>
<resource-env-ref-type>javax.jms.Topic</resource-env-ref-type>
<lookup-name>jms/myTopic</lookup-name>
</resource-env-ref>
or if your resource-ref lacks lookup-name and you instead have a ibm-web-bnd.xml file with a binding-name,
<resource-ref name="java:comp/env/jms/topicRef" binding-name="jms/myTopic">
</resource-ref>
then specify jms/myTopic as the JNDI name of the Topic.
Application code will then be able to do:
Topic topic = InitialContext.doLookup("java:comp/env/jms/topicRef");
Some optimizations/special cases:
If you have neither lookup-name nor binding-name, then WebSphere Application Server computes a default binding via the resource reference name. If this is the case for your resource reference, then you will have a deployment descriptor such as the following without any bindings file,
<resource-ref>
<res-ref-name>jms/myTopicConnectionFactory</res-ref-name>
<res-type>javax.jms.TopicConnectionFactory</res-type>
</resource-ref>
In the above case, specify jms/myTopicConnectionFactory as the JNDI name.
The application will be able to look it up as,
TopicConnectionFactory tcf = InitialContext.doLookup("java:comp/env/jms/myTopicConnectionFactory");
I try to deploy a Java EE Application containing several EJB Timer Services (with persistence=true).
The server complains that no datasource was defined:
Caused by: javax.ejb.EJBException: See nested exception; nested exception is: java.lang.IllegalStateException: The ejbPersistentTimer feature is enabled, but the defaultEJBPersistentTimerExecutor persistent executor cannot be resolved. The most likely cause is that the DefaultDataSource datasource has not been configured. Persistent EJB timers require a datasource configuration for persistence.
The ejbPersistentTimer-3.2 feature is turned on.
I can not find an example how to configure such a datasource in the server.xml file
I tried:
<dataSource id="timerDataSource" jndiName="jdbc/timerDataSource">
</dataSource>
<databaseStore id="EJBTimerDatabaseStore"
tablePrefix="EJBTimer_" dataSourceRef="timerDataSource" />
<persistentExecutor
id="defaultEJBPersistentTimerExecutor"
taskStoreRef="EJBTimerDatabaseStore" />
But this seems to be not enoght? Did I need to activate DerbyDB as a feature too?
It looks like your <dataSource> configuration is missing a few items:
A <jdbcDriver> which points to the JDBC driver jar that corresponds with the DB you are using
A <properties> element which identifies DB properties such as the DB server's hostname, port, and DB name.
Since you mentioned using DerbyDB, here is an example of what Derby config might look like:
<dataSource id="timerDataSource" jndiName="jdbc/timerDataSource">
<jdbcDriver libraryRef="DerbyLib"/>
<properties.derby.embedded databaseName="${server.config.dir}/data/EJBTimerDB" createDatabase="create"/>
</dataSource>
<library id="DerbyLib">
<fileset dir="${server.config.dir}/derbyDriverDir/"/>
</library>
For additional info on configuring DataSources in Liberty, check out this doc:
Configuring relational database connectivity in Liberty
am facing NonSqlTransientException Null userid not supported while starting the liberty server where my server.xml contain authdata
The authData configuration in Liberty is only for container managed authentication. If you are using application authentication (as is the case for JNDI lookup without resource reference, or if using a resource reference that is set to authentication type of Application), then authData does not apply. If you are using a resource reference with Container authentication, then you can use the authData, but there is an additional configuration step to associate the authData with the dataSource. This can be done in either of the following ways, documented in this knowledge center article.
One option is to configure the containerAuthDataRef of the dataSource to point at the id of the authData element (you'll need to add an id for it if it doesn't have one). Here is an example,
<authData id="myAuth" user="user1" password="pwd1"/>
<dataSource jndiName="jdbc/myDataSource" containerAuthDataRef="myAuth">
<jdbcDriver libraryRef=...
<properties...
</dataSource>
The other option is to specify the authData's id under the authentication-alias in the application's bindings (such as ibm-web-bnd.xml or ibm-ejb-jar-bnd.xml) for the data source. For example, the following bindings are based on the server config from the previous example,
<resource-ref name="java:app/env/jdbc/myDataSourceRef" binding-name="jdbc/myDataSource">
<authentication-alias name="myAuth"/>
</resource-ref>
It should be noted that the former is a default for container authentication that is used in the absence of the latter. So if you specify both ways, then the latter takes precedence and will be used instead.
I have some Java code running on Liberty Profile which authenticates with MS Active Directory and makes LDAP searches. The code use JNDI and does what it is intended to do. The problem is that the LDAP parameters are hard coded in Java. Works, but could be improved:
ldap.put(Context.PROVIDER_URL, "ldap://ad.foo.bar:389");
ldap.put(Context.SECURITY_PRINCIPAL, "CN=account,OU=A,DC=ad,DC=foo,DC=bar");
ldap.put(Context.SECURITY_CREDENTIALS, "apoorlykeptsecret");
...
ldapCtxt = new InitialDirContext(ldap);
Is it possible to pick the LDAP properties up from an ldapRegistry element in the server.xml file instead? Or am I on the wrong track? Is there a better way to approach this?
Yes, you should be able to configure that using the <ldapRegistry> element in server.xml.
For example:
<ldapRegistry id="ldap" realm="SampleLdapADRealm"
host="ldapserver.mycity.mycompany.com" port="389"
baseDN="cn=users,dc=adtest,dc=mycity,dc=mycompany,dc=com"
bindDN="cn=testuser,cn=users,dc=adtest,dc=mycity,dc=mycompany,dc=com"
bindPassword="testuserpwd"
ldapType="Microsoft Active Directory">
<activedFilters
userFilter="(&(sAMAccountName=%v)(objectcategory=user))"
groupFilter="(&(cn=%v)(objectcategory=group))"
userIdMap="user:sAMAccountName"
groupIdMap="*:cn"
groupMemberIdMap="memberOf:member" >
</activedFilters>
</ldapRegistry>
For full doc see: Configuring LDAP user registries in Liberty
As an alternative quick approach, you could put those values in your server.xml configuration as JNDI entries and obtain the values in your application by JNDI lookup. For example:
<jndiEntry jndiName="ldap/provider_url" value="ldap://ad.foo.bar:389"/>
<jndiEntry jndiName="ldap/secuirty_principal" value="CN=account,OU=A,DC=ad,DC=foo,DC=bar"/>
<!-- WARNING: Storing passwords is JNDI is not secure -->
<jndiEntry jndiName="ldap/security_credentials" value="apoorlykeptsecret"/>
String providerUrl = InitialContext.doLookup("ldap/provider_url");
// etc...