eclipse-ee4j / glassfish

Eclipse GlassFish
https://eclipse-ee4j.github.io/glassfish/
379 stars 144 forks source link

NullPointerException in com.sun.enterprise.resource.pool.PoolManagerImpl.getJavaName #15443

Closed glassfishrobot closed 13 years ago

glassfishrobot commented 13 years ago

calling getConnection on a DataSource results in an intermittent NullPointerException in getJavaName as follows:

com.sun.enterprise.resource.pool.PoolManagerImpl.getJavaName(PoolManagerImpl.java:539) com.sun.enterprise.resource.pool.PoolManagerImpl.getResourceReference(PoolManagerImpl.java:530) com.sun.enterprise.connectors.ConnectionManagerImpl.allocateConnection(ConnectionManagerImpl.java:175) com.sun.enterprise.connectors.ConnectionManagerImpl.allocateConnection(ConnectionManagerImpl.java:165) com.sun.enterprise.connectors.ConnectionManagerImpl.allocateConnection(ConnectionManagerImpl.java:160) com.sun.gjc.spi.base.DataSource.getConnection(DataSource.java:110) com.kickstone.pricegoblin.data.goblin.GoblinData.getProduct(GoblinData.java:173) ...

where the calling class is defined as: @ManagedBean public class GoblinData { ... public void getProduct(URI uri){ ... Retailer retailer=null; try

{ retailer=(Retailer)em.createNamedQuery("Retailer.findByExternalUri").setParameter("externalUri", externalUri).getSingleResult(); }

catch (NoResultException ex)

{ return; // TODO - retailer not matched }

... try { Connection c=null; try

{ c=ds.getConnection(); ... }

finally

{ if (c!=null) c.close(); }

} catch (SQLException ex){ } }

@PersistenceContext(unitName="PriceGoblinPU") private EntityManager em;

@Resource(mappedName="jdbc/frontendDB") private DataSource ds; }

and the datasource is defined as:

Looking at the code, the only time logicalName is null (which is passed to getJavaName) is when an entityManager is used, if a DataSource is injected, it is always set.

If you require any more info, then let me know

Environment

Linux

Affected Versions

[3.1_dev]

glassfishrobot commented 6 years ago
glassfishrobot commented 13 years ago

@glassfishrobot Commented jsl123 said: Apologies, this has somehow been assigned to the load-balancer component. I thought I left the component selection blank.

glassfishrobot commented 13 years ago

@glassfishrobot Commented @h2002044 said: Please provide a test-case (eg: .war) which can be used to reproduce the issue, if it is easy for you.

glassfishrobot commented 13 years ago

@glassfishrobot Commented jsl123 said: I'll try and get a test case, but it happens only intermittently and I've only seen it on our forward facing boxes with reasonably high load. The only thing I've noticed is that it occurred more frequently when I'd inadvertently used the debug connection pool settings which had a very small pool, so I figured it was related to the connection pool having no spare connections.

glassfishrobot commented 13 years ago

@glassfishrobot Commented @h2002044 said: Looking at the stack trace, this issue can happen only in the following setup. Application component has multiple "resource-ref"s defined for same resource.

eg: jdbc-resource by jndi-name "my-resource" is referred by (atleast) two resource-refs

logical-name-1 my-resource logical-name-2 my-resource

Workaround would be to a) Use same logical-name (only one resource-ref per resource) in the application or b) Create another resource pointing to same pool and map it for the second resource-ref. [This is simple as jdbc-resource is referring the jdbc-connection-pool and jdbc-connection-pool is shared by multiple jdbc-resources.]

Please confirm whether your setup is similar to the environment stated above and the workaround solves your issue.

Changing the priority as we are gone past HCF and workaround is available.

glassfishrobot commented 13 years ago

@glassfishrobot Commented jsl123 said: On my forward facing server, I have 2 resource-refs defined as follows in the domain.xml config file:

neither includes a jndi name explicitly, but use the resource with the same name. both resources point to different pools. On my debug machines, the resource-refs are the same, the only difference is that the 2 resources point at the same connection pool.

Other than the global config, I don't define any references in my application config files.

I've also been working on a test case and I may be able to replicate it using jmeter and loading up the requests - I need to verify the results are repeatable.

Additionally, debugging the app, the multiple references are caused by the fact I inject the datasource into multiple managed beans. The list it iterates through contains a list along the lines of: com.kickstone.pricegoblin.resources.Home/ds com.kickstone.pricegoblin.data.GoblinData/ds etc if that helps

glassfishrobot commented 13 years ago

@glassfishrobot Commented jsl123 said: Some more information - I can get partial repeatability with my main app using jmeter, so going to strip out the relevant parts and post a sample war file. In addition, the problem is with logicalName, it just happens to be triggered if there are multiple references defined. Looking through the source and partially debugging it, this could be a problem with Weld not setting the logical name and thus leaving it as null.

glassfishrobot commented 13 years ago

@glassfishrobot Commented @h2002044 said: I could make the following use-case resulting in NPE.

eg:

Class MyBean { @Resource(mappedName="jdbc/__default") DataSource ds1;

@Resource(mappedName="jdbc/__default") DataSource ds2;

private void doDBOperation()

{ InitialContext ic = new InitialContext(); DataSource ds = (DataSource) ic.lookup("jdbc/__default") Connection con = ds.getConnection(); // FAIL with same NPE as reported in the initial bug-report }

}

Doing an initialContext.lookup("jdbc/default") in the class where two DataSources (of same resource-name ie., "jdbc/default) is injected or specified via in application descriptors will result in the above NPE.

Fix would be to make sure that "logicalName" is not null while comparing the resource-ref names. logicalName will be null in case of jndi-name based (physical) lookups. (eg: initialContext.lookup('jdbc/__default')

jsl123 : Please let me know whether your code-base has initialContext based lookup of resource in the class where the same resource is also injected multiple times. (similar to above use-case)

glassfishrobot commented 13 years ago

@glassfishrobot Commented jsl123 said: Netbeans Web Archive Project that exhibits the described behaviour

glassfishrobot commented 13 years ago

@glassfishrobot Commented jsl123 said: Hi, I've attached a test case that demonstrates the problem on my machine running pretty much a vanilla Glassfish v3.1.36 install. I've stripped out everything from my main project that doesn't seem to be needed.

I don't follow the schema of your testcase as my classes are managed beans and the datasource is injected by the container, finally the multiple references are in separate classes and have different logicalNames - see below for details of testcase

I only use the datasource.getConnection so that I can generate Arrays which are vendor specific. The tables, database settings will need changing to meet your needs, otherwise it should be fairly straightforward. The project includes a jmeter test which causes the problem about 1 in 500 hits although you need to heavily load it to get a failure so ramping up of the settings may be needed - equally I could only see the error when not in the debugger...

The project contains the following features which seem to contribute to the problem:

The test case doesn't really do anything, although as it stands the first db call should succeed in order to get the connection and trigger the error.

Let me know if you have any problems (or I've done something stupid in my implementation)

glassfishrobot commented 13 years ago

@glassfishrobot Commented @h2002044 said: Thanks for sharing the test-case, I tried the test-case using jmeter and could not reproduce it in varied load, multiple times.

I use an entity Manager (based on a persistenceUnit using the same database resource) as well as this seems to have null for the logicalName, in addition its jdni name has _nontx appended - which I found confusing.

Yes, JPA uses the resource (in persistence.xml) which will account for physical lookup with __nontx suffix which is for internal purposes to get a non-transactional connection. This is expected.

the Datasource is injected into 2 different classes (home & goblindata) which result in the 2 distinct references in getResourceReference Yes, since these are defined in the .war, all of the resource-references (@Resource) will be shared within the jndi environment of the .war.

glassfishrobot commented 13 years ago

@glassfishrobot Commented jsl123 said: Hi, do you have a matching entry in the retailer table to the url passed into the rest method? Otherwise as the code stands it will drop out and therefore doesn't create the connection explictly from the Datasource which is what results in the error. For reference, the error happens on line 45 in GoblinData.java.

You may also need to create another table:

CREATE TABLE django.summary_map ( id integer primary key, offer_id integer, template integer, position integer, value character varying )

which is used, although I only use a query against it so merged the query into the retailer entity object so you may not have spotted it...

glassfishrobot commented 13 years ago

@glassfishrobot Commented @h2002044 said: How bad is its impact? (Severity)

How much effort is required to fix it? (Cost)

What is the risk of fixing it? (Risk)

Does a work around for the issue exist? Can the workaround be reasonably employed by the end user?

If the issue is not fixed should the issue and its workaround (if applicable) be described in the Release Notes?

All tests passed : QL (Web, Classic), connector-dev, jdbc-dev, connector-standalone-cts (Web, Classic), resources-admin-cli and the use-case I have posted. Since I could not reproduce the exact setup by the bug-submitter, requested bug-submitter to test the fix and got confirmation that the fix resolves the issue for him.

Will also add a dev-test for this scenario.

glassfishrobot commented 13 years ago

@glassfishrobot Commented @h2002044 said: svn log -v -r 44427

Modified Paths:

trunk/v3/connectors/connectors-runtime/src/main/java/com/sun/enterprise/resource/pool/PoolManagerImpl.java

Also added a test-case : refer README svn log -v -r 44429 Modified Paths:

trunk/v2/appserv-tests/devtests/jdbc/connsharing/nonxa/ejb/SimpleSession.java trunk/v2/appserv-tests/devtests/jdbc/connsharing/nonxa/descriptor/ejb-jar.xml trunk/v2/appserv-tests/devtests/jdbc/connsharing/nonxa/ejb/SimpleSessionBean.java trunk/v2/appserv-tests/devtests/jdbc/connsharing/nonxa/client/Client.java trunk/v2/appserv-tests/devtests/jdbc/connsharing/nonxa/README

glassfishrobot commented 13 years ago

@glassfishrobot Commented File: NPEBugTest.zip Attached By: jsl123

glassfishrobot commented 7 years ago

@glassfishrobot Commented This issue was imported from java.net JIRA GLASSFISH-15443

glassfishrobot commented 13 years ago

@glassfishrobot Commented Reported by jsl123

glassfishrobot commented 13 years ago

@glassfishrobot Commented Marked as fixed on Tuesday, January 11th 2011, 7:30:46 pm