I have deployed a mature web application to a new server on tomcat 7. The database the system uses is quite empty as we're in the early stages of configuring it for use.
Going to the app, you get a login page. Log in and it usually takes you to the main page of the app.
But after coming in the following morning, we always get the same problem:
We bring up the login screen - no problem
Enter our username and password - system hangs
We go to tomcat and using
the system tray, stop the service.
The stopping service progress bar appears then goes away, but the status
on the tomcat properties dialog still shows 'Started' and both the Start
and Stop buttons are disabled.
We check the tomcat logs and there are no errors
We restart the server and it works ok again
There is nothing obvious we can see. A tomcat 'Find Leaks' request shows nothing, and looking at the heap sizes on VisualVM shows a consistent pattern of heap takeup followed by garbage collection bringing it back down to the same low level (so no apparent leaks)
I thought it may be mysql connections timing out, but that shouldnt be the case because if I log in with the wrong password, the system goes to the database to check the password and returns as expected with 'wrong password'. The only point at which it fails is if you enter the correct password.
The only clue we have is that there is an error when logging in, where the system uses some custom code to figure out the users' host name:
2019-02-14 08:10:14,277 08:10:14.277 [http-bio-8080-exec-9] ERROR com.sw.app.ui.UserAuthenticatedWebSession - Unknown host!
java.net.UnknownHostException: null
at java.net.Inet6AddressImpl.getHostByAddr(Native Method) ~[na:1.8.0_201]
at java.net.InetAddress$2.getHostByAddr(Unknown Source) ~[na:1.8.0_201]
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.8.0_201]
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source) ~[na:1.8.0_201]
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source) ~[na:1.8.0_201]
at java.lang.reflect.Method.invoke(Unknown Source) ~[na:1.8.0_201]
at com.sw.app.data.utils.NetUtilities.getHostName(NetUtilities.java:114) ~[app-data-4.0.15.1-SNAPSHOT.jar:na]
This is only invoked if the user logs in successfully to store where they are logging in from, but the exception is caught in the code and then just logged rather than propagated upwards, and then we use a default 'unknown' host name. This is the code:
public static String getHostName( InetAddress inaHost ) throws UnknownHostException
{
try {
Class<? extends InetAddress> clazz = Class.forName( "java.net.InetAddress" ).asSubclass( InetAddress.class );
Constructor<?>[] constructors = clazz.getDeclaredConstructors();
constructors[0].setAccessible( true );
InetAddress ina = (InetAddress)constructors[0].newInstance();
Field[] fields = ina.getClass().getDeclaredFields();
for( Field field : fields ) {
// Depends on the version of java we are dealing with:
// Older version - single nameservice
if( field.getName().equals( "nameService" ) ) {
return getHostName( field.get( null ), inaHost );
} else if( field.getName().equals( "nameServices" ) ) {
// newer version - multiple name services possible
StringBuilder builder = new StringBuilder();
field.setAccessible( true );
// A list of nameservice objects
#SuppressWarnings( "unchecked" )
List<Object> nameServices = (List<Object>)field.get( null );
for( Object nameService : nameServices ) {
String hostName = getHostName( nameService, inaHost );
if( builder.length() > 0 ) {
builder.append( ", " );
}
builder.append( hostName );
}
return builder.toString();
}
}
} catch( ClassNotFoundException cnfe ) {
throw new InvalidOperationException( "Class not found when looking up host name", cnfe );
} catch( IllegalAccessException iae ) {
throw new InvalidOperationException( "Cannot access method/field", iae );
} catch( InstantiationException ie ) {
throw new InvalidOperationException( "Cannot instantiate class", ie );
} catch( InvocationTargetException ite ) {
throw (UnknownHostException)ite.getCause();
}
return null;
}
/**
* Get the host name using reflection on the hidden class implementation of the InetAddress details.
* #param p_nameService
* #param p_address
* #return
* #throws IllegalAccessException
* #throws InvocationTargetException
*/
private static String getHostName( Object nameService, InetAddress address ) throws IllegalAccessException, InvocationTargetException {
Method[] methods = nameService.getClass().getDeclaredMethods();
for( Method method : methods ) {
// The nameService is assumed to have a method, getHostByAddr, which takes the byte[] inet address
if( method.getName().equals( "getHostByAddr" ) ) {
method.setAccessible( true );
return (String)method.invoke( nameService, address.getAddress() );
}
}
return "";
}
Does anyone have similar issues?
-- Edit --
Here is the database configuration bean class.
#Configuration
public class AppPersistence {
private static final Logger LOGGER = LoggerFactory.getLogger( AppPersistence.class );
protected static final String INTERNAL_IP_DOMAIN = "*******";
protected static final String JDBC_PROTOCOL = "jdbc:mysql://";
protected static final String DEFAULT_DATABASE_NAME = "*******";
/** The path for context-based property lookups */
protected static final String CONTEXT_LOOKUP_PATH = "java:comp/env";
/** This is the default location for the database - on the same machine as the deployment */
protected static final String DB_LOCAL = JDBC_PROTOCOL + "localhost:3306/" + DEFAULT_DATABASE_NAME;
#Bean
public DataSource createDataSource() throws Exception {
BasicDataSource source = new BasicDataSource();
// allow for parameterised config
source.setDriverClassName( Driver.class.getName() );
source.setUrl( getProperty( "app.database.url", DB_LOCAL ) );
source.setUsername( getProperty( "app.database.username", "*****" ) );
source.setPassword( getProperty( "app.database.password", "****" ) );
LOGGER.warn( "Connecting to: " + source.getUrl() );
return source;
}
protected String getProperty( String name, String default ) {
// first check system properties
String val = System.getProperty( name );
if( val != null ) {
logLookup( "System Properties", name, val );
return val;
}
// check environment variables
val = System.getenv( name );
if( val != null ) {
logLookup( "System Environment Variables", name, val );
return val;
}
// if we are deployed to a container, check the environment variables in that.
try {
Context context = InitialContext.doLookup( "java:comp/env" );
if( context != null ) {
Object valObj = context.lookup( name );
if( valObj != null ) {
logLookup( "Context", name, valObj.toString() );
return valObj.toString();
}
}
} catch( NamingException e ) {
// if running on a dev machine this will probably happen
LOGGER.warn( "Could not find context for lookup of " + p_name + " - assuming running in dev mode with defaults. Error was: " + e.toString( true ) );
LOGGER.info( "Error received on lookup of " + name + ":", e );
}
return p_default;
}
protected void logLookup( String source, String lookup, String value ) {
if( value.contains( "password" ) ) {
// avoid displaying any password info
LOGGER.warn( "Successfully looked up sensitive value from " + source + " for name '" + lookup + "': [******]" );
} else {
LOGGER.warn( "Successfully looked up value from " + source + " for name '" + lookup + "': '" + value + "'" );
}
}
#Bean
public LocalContainerEntityManagerFactoryBean entityManagerFactory( DataSource dataSource ) {
LocalContainerEntityManagerFactoryBean entityManagerFactory = new LocalContainerEntityManagerFactoryBean();
entityManagerFactory.setPersistenceUnitName( "com.sw.app.data.persistence" );
entityManagerFactory.setDataSource( dataSource );
entityManagerFactory.setJpaVendorAdapter( new HibernateJpaVendorAdapter() );
entityManagerFactory.setLoadTimeWeaver( new InstrumentationLoadTimeWeaver() );
entityManagerFactory.setJpaDialect( new HibernateJpaDialect() );
entityManagerFactory.setPackagesToScan( "com.sw.app.data", "com.sw.app.rawimport",
"com.sw.app.view", "com.sw.app.warranty" );
entityManagerFactory.setJpaPropertyMap( hibernateJpaProperties( dataSource ) );
return entityManagerFactory;
}
private Map<String, ?> hibernateJpaProperties( DataSource dataSource ) {
HashMap<String, String> properties = new HashMap<>();
// Need to copy these values over, otherwise c3p0 can't see them.
if( dataSource instanceof BasicDataSource ) {
BasicDataSource source = (BasicDataSource)p_dataSource;
properties.put( "hibernate.connection.driver_class", source.getDriverClassName() );
properties.put( "hibernate.connection.url", source.getUrl() );
properties.put( "hibernate.connection.username", source.getUsername() );
properties.put( "hibernate.connection.password", source.getPassword() );
}
// Added to avoid some merge problems when updating entities (eg contact to custimport)
properties.put( "hibernate.event.merge.entity_copy_observer", "allow" );
// Second level cache
properties.put( "hibernate.cache.use_second_level_cache", "true" );
properties.put( "hibernate.cache.use_query_cache", "true" );
properties.put( "hibernate.cache.provider_class", "org.hibernate.cache.EhCacheProvider" );
properties.put( "hibernate.cache.region.factory_class", EhCacheRegionFactory.class.getName() );
properties.put( "hibernate.generate_statistics", "false" );
properties.put( "hibernate.show_sql", "false" );
properties.put( "hibernate.format_sql", "false" );
// validate | update | create | create-drop -->
properties.put( "hibernate.hbm2ddl.auto", "update" );
properties.put( "hibernate.dialect", MySQL5Dialect.class.getName() );
// [main] WARN org.hibernate.cfg.AnnotationBinder - HHH000457: Joined inheritance hierarchy [com.sw.system4.data.collateral.AbstractCollateral] defined explicit #DiscriminatorColumn. Legacy Hibernate behavior was to ignore the #DiscriminatorColumn. However, as part of issue HHH-6911 we now apply the explicit #DiscriminatorColumn. If you would prefer the legacy behavior, enable the `hibernate.discriminator.ignore_explicit_for_joined` setting (hibernate.discriminator.ignore_explicit_for_joined=true) -->
properties.put( "hibernate.discriminator.ignore_explicit_for_joined", "true" );
//properties.put("hibernate.hbm2ddl.import_files", "insert-data.sql");
//properties.put("hibernate.ejb.naming_strategy", "org.hibernate.cfg.ImprovedNamingStrategy");
// This wasnt required in persistence.xml, but for some reason is here.
properties.put( "hibernate.connection.provider_class", C3P0ConnectionProvider.class.getName() );
// just adding c3p0 props was enough in persistence.xml, but not here.
properties.put( "hibernate.c3p0.min_size", "5" );
properties.put( "hibernate.c3p0.max_size", "20" );
properties.put( "hibernate.c3p0.timeout", "300" ); // 5mins
properties.put( "hibernate.c3p0.max_statements", "50" );
properties.put( "hibernate.c3p0.idle_test_period", "100" );
properties.put( "hibernate.c3p0.preferredTestQuery", "select 1" );
properties.put( "hibernate.c3p0.testConnectionOnCheckout", "true" );
properties.put( "hibernate.c3p0.numHelperThreads", "12" );
properties.put( "hibernate.c3p0.maxStatementsPerConnection", "25" );
properties.put( "hibernate.c3p0.statementCacheNumDeferredCloseThreads", "1" );
return l_properties;
}
#Bean
public JpaTransactionManager transactionManager( EntityManagerFactory emf ) {
JpaTransactionManager jpaTransactionManager = new JpaTransactionManager();
jpaTransactionManager.setEntityManagerFactory( emf );
return jpaTransactionManager;
}
}
What is your database? Is it a Cloud Database? I had a similar problem with CloudSQL. What happened was when some active connections didn't do anything with the database, from the database side, it rejects the connection after some hours. But on the application side, you will see it as an active connection. I have used Apache DBCP pool, and I was able to solve the problem using this in the database configurations.
dataSource.setValidationQuery("SELECT 1");
dataSource.setTestOnBorrow(true);
dataSource.setTestWhileIdle(true);
Because you are using C3P0, following commands should work for you.
hibernate.dbcp.testOnBorrow=true
hibernate.dbcp.testOnReturn=true
hibernate.dbcp.validationQuery=SELECT 1
In my project I am using cucumber with junit, maven and selenium webdriver inclusive with java and extent report.
My extent report is generated in an folder 'output' and within the same folder screenshot of failed test-cases are also saved.
After execution of test and generation of report I want to compress the folder 'output' into zip file and mail it.
Issue : At the instance when my code converts the file into zip format, the test-report is not yet generated (as it generates after completion of all test cases) so when 'output' folder is compressed it only contains the failed screenshot and same is being mailed..
Please suggest
this is my runner file
this is my hooks class
This is my runner class...............
#CucumberOptions(
features = {"featurefiles/DefineStaffType.feature"}
, glue = {"stepdefinitions"}
, monochrome = true
, plugin = {"pretty:STDOUT",
"json:target/cucumber.json",
"junit:target/cucumber.xml",
"com.cucumber.listener.ExtentCucumberFormatter:output/report.html"}
, tags = {"#Scenario1, #Scenario2, #Scenario3"}
)
public class DefineStaffTypeRunner {
#AfterClass
public static void reportSetup ( ) throws IOException, EmailException {
Reporter.loadXMLConfig ( new File ( "configuration\\extentconfig.xml" ) );
Reporter.setSystemInfo ( "User Name", System.getProperty ( "user.name" ) );
Reporter.setSystemInfo ( "Time Zone", System.getProperty ( "user.timezone" ) );
Reporter.setSystemInfo ( "64 Bit", "Windows 10" );
Reporter.setSystemInfo ( "3.1.0", "Selenium" );
Reporter.setSystemInfo ( "1.9", "Maven" );
Reporter.setSystemInfo ( "1.9", "Java Version" );
Reporter.setTestRunnerOutput ( "Define Staff Type " );
FileConversion.convertToZip ( "output" );
new MailHandlingUtility ( ).sendMailWithAttachment ( );
}
}
This is my hooks class
public class CucumberHooks extends GenericBaseClass {
DriverMethods dm = new DriverMethods ( );
CaptureScreenshot cs = new CaptureScreenshot ( );
static MailHandlingUtility mhu = new MailHandlingUtility ( );
#Before
public void launchBrowser (Scenario currentscenario) throws IOException {
this.scenario = currentscenario;
driver = getCurrentDriver ( );
dm.maximizeWindow ( );
}
#After
public void tearDownScenario (Scenario currentscenario) throws IOException, EmailException {
scenario.write ( "Scenario is finished" + currentscenario );
cs.catureScreenshot ( (Scenario) scenario );
driver.close ( );
driver.quit ( );
driver = null;
}
}
I'm trying to get FutureCallbacks from Guava working because I want to use it in my java api for cloudflare.
Test class:
import com.google.common.util.concurrent.*;
import javax.annotation.Nullable;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class Test {
#org.junit.Test
public static void apiUsersCode( ) {
apiMethodThatReturnsCloudflareInfos( new FutureCallback<String>() {
#Override
public void onSuccess( #Nullable String result ) {
System.out.println( "WORKING" );
}
#Override
public void onFailure( Throwable t ) {
System.out.println( t );
}
} );
}
public static void apiMethodThatReturnsCloudflareInfos( FutureCallback<String> usersFutureCallback ) {
Callable<String> solution = ( ) -> {
Thread.sleep( 1000L ); // simulate slowness of next line
return "http output"; // this is this other method that sends a http request
};
// runs callable async, when done: execute usersFutureCallback
ExecutorService executor = Executors.newFixedThreadPool( 10 );
ListeningExecutorService service = MoreExecutors.listeningDecorator( executor );
ListenableFuture<String> listenableFuture = service.submit( solution );
Futures.addCallback( listenableFuture, usersFutureCallback, service );
}
}
When someone uses this api simplified:
He calls a method and pass a FutureCallback object (usersFutureCallback)
This method runs another method where its output is returned in the callable
Done
Example Api method that is beeing executed by the user
apiMethodThatReturnsCloudflareInfos( new FutureCallback<String>() {
#Override
public void onSuccess( #Nullable String cloudflareOutput ) {
System.out.println( "WORKING" );
}
#Override
public void onFailure( Throwable t ) {
System.out.println( t );
}
} );
Example api methods simplefied doing
public static void apiMethodThatReturnsCloudflareInfos( FutureCallback<String> usersFutureCallback ) {
Callable<String> solution = ( ) -> {
Thread.sleep( 1000L ); // simulate slowness of next line
return "http output"; // this is this other method that sends a http request
};
// runs callable async, when done: execute usersFutureCallback
ExecutorService executor = Executors.newFixedThreadPool( 10 );
ListeningExecutorService service = MoreExecutors.listeningDecorator( executor );
ListenableFuture<String> listenableFuture = service.submit( solution );
Futures.addCallback( listenableFuture, usersFutureCallback, service );
}
"WORKING" is only printed when changing and adding this lines to add the listener after the callable is done.
But that is not the solution of cause.
public static void apiMethodThatReturnsCloudflareInfos( FutureCallback<String> usersFutureCallback ) {
Callable<String> solution = ( ) -> {
Thread.sleep( 1000L ); // simulate slowness of next line
return "http output"; // this is this other method that sends a http request
};
// runs callable async, when done: execute usersFutureCallback
ExecutorService executor = Executors.newFixedThreadPool( 10 );
ListeningExecutorService service = MoreExecutors.listeningDecorator( executor );
ListenableFuture<String> listenableFuture = service.submit( solution );
// i don't want that
try {
Thread.sleep( 10001L );
} catch ( InterruptedException e ) {
e.printStackTrace();
}
Futures.addCallback( listenableFuture, usersFutureCallback, service );
}
What am I doing wrong?
The problem lies in how you are testing that method. You basically create a new thread that runs your Callable<String> solution, but nothing will wait for that thread to finish. Once your test method is finished, your test suite will terminate and with it the thread that is running solution.
In a real life scenario, where your application lives longer than solution, you won't encounter that problem.
To solve this, you must update your test case to not terminate prematurely. You could do this by updating the apiUsersCode() to set some value in onSuccess and onFailure, which you wait for after calling apiMethodThatReturnsCloudflareInfos.
Solved!
The problem was the test suit JUnit.
It worked when testing it in a main(String[] args) method.
...everything is correct only what should help me with the tests makes the mistake :D
#Test
public void apiUsersCode( ) {
apiMethodThatReturnsCloudflareInfos( new FutureCallback<String>() {
#Override
public void onSuccess( #Nullable String result ) {
System.out.println( "WORKING" );
}
#Override
public void onFailure( Throwable t ) {
System.out.println( t );
}
} );
try {
new CountDownLatch( 1 ).await(2000, TimeUnit.MILLISECONDS);
} catch ( InterruptedException e ) {
e.printStackTrace();
}
}
public static void apiMethodThatReturnsCloudflareInfos( FutureCallback<String> usersFutureCallback ) {
Callable<String> solution = ( ) -> {
Thread.sleep( 1000L ); // simulate slowness of next line
return "http output"; // this is this other method that sends a http request
};
// runs callable async, when done: execute usersFutureCallback
ExecutorService executor = Executors.newFixedThreadPool( 10 );
ListeningExecutorService service = MoreExecutors.listeningDecorator( executor );
ListenableFuture<String> listenableFuture = service.submit( solution );
Futures.addCallback( listenableFuture, usersFutureCallback, service );
}
I have to work with an already existing Eclipse RAP application which contains of two features and around 40 dependencies.
Since the Eclipse RAP doesn't have a preStartup() method I call the update procedure in the RAP's start() method:
public class MyApplication implements IApplication
{
#Override
public Object start( IApplicationContext context ) throws Exception
{
P2Util.update();
...
}
}
The IProvisioningAgent is not null, the IMetadataRepositoryManager and IArtifactRepositoryManager are correctly initialized.
public static boolean configureRepository( IProvisioningAgent agent )
{
String repo = "file:///c:/export/repository/"; // TODO HERE!
log.debug( "Initiliazing Repository Managers" );
IMetadataRepositoryManager metadataManager = ( IMetadataRepositoryManager ) agent.getService( IMetadataRepositoryManager.SERVICE_NAME );
IArtifactRepositoryManager artifactManager = ( IArtifactRepositoryManager ) agent.getService( IArtifactRepositoryManager.SERVICE_NAME );
URI uri;
try
{
uri = new URI( repo );
}
catch ( URISyntaxException e1 )
{
log.error( "Unexpected URISyntaxException, the specified path is not a valid URI", e1 ); //$NON-NLS-1$
return false;
}
if ( metadataManager == null )
{
log.error( "IMetadataRepositoryManager instance is null!" );
return false;
}
metadataManager.addRepository( uri );
log.debug( "Added repository to MetadataManager: " + repo );
if ( artifactManager == null )
{
log.error( "IArtifactRepositoryManager instance is null!" );
return false;
}
artifactManager.addRepository( uri );
log.debug( "Added repository to ArtifactManager: " + repo );
return true;
}
Still one problem occurs all the time after I call checkForUpdates().
public static IStatus checkForUpdates( IProvisioningAgent agent ) throws OperationCanceledException
{
log.info( "Checking for new updates in repository" );
ProvisioningSession session = new ProvisioningSession( agent );
UpdateOperation operation = new UpdateOperation( session );
IStatus status = operation.resolveModal( new NullProgressMonitor() );
return status;
}
It returns the following status:
Status OK: org.eclipse.equinox.p2.operations code=10001 Your original request has been modified. null children=[]
I have already checked the flag "Support software installation in the launched application" in my run configuration, the problem persists.
I am trying to use the 'Hello World' for Neo4j. The problem is that I when I boot up the server and check the neo4j's browser (localhost:7474), I cannot see any graphic visualisation of my nodes.
import java.io.File;
import org.neo4j.graphdb.Direction;
import org.neo4j.graphdb.GraphDatabaseService;
import org.neo4j.graphdb.Node;
import org.neo4j.graphdb.Relationship;
import org.neo4j.graphdb.RelationshipType;
import org.neo4j.graphdb.Transaction;
import org.neo4j.graphdb.factory.GraphDatabaseFactory;
public class MyFirstMain
{
private static final String DB_PATH = "/neo4j/data/graph.db";
public String greeting;
// START SNIPPET: vars
GraphDatabaseService graphDb;
Node firstNode;
Node secondNode;
Relationship relationship;
// END SNIPPET: vars
// START SNIPPET: createReltype
private static enum RelTypes implements RelationshipType
{
KNOWS
}
// END SNIPPET: createReltype
public static void main( final String[] args )
{
MyFirstMain hello = new MyFirstMain();
hello.createDb();
// hello.removeData();
// hello.shutDown();
}
void createDb()
{
// START SNIPPET: startDb
graphDb = new GraphDatabaseFactory().newEmbeddedDatabase( DB_PATH );
registerShutdownHook( graphDb );
// END SNIPPET: startDb
// START SNIPPET: transaction
try ( Transaction tx = graphDb.beginTx() )
{
// Database operations go here
// END SNIPPET: transaction
// START SNIPPET: addData
firstNode = graphDb.createNode();
firstNode.setProperty( "message", "Hello, " );
secondNode = graphDb.createNode();
secondNode.setProperty( "message", "World!" );
relationship = firstNode.createRelationshipTo( secondNode, RelTypes.KNOWS );
relationship.setProperty( "message", "brave Neo4j " );
// END SNIPPET: addData
// START SNIPPET: readData
System.out.print( firstNode.getProperty( "message" ) );
System.out.print( relationship.getProperty( "message" ) );
System.out.print( secondNode.getProperty( "message" ) );
// END SNIPPET: readData
greeting = ( (String) firstNode.getProperty( "message" ) )
+ ( (String) relationship.getProperty( "message" ) )
+ ( (String) secondNode.getProperty( "message" ) );
// START SNIPPET: transaction
tx.success();
}
// END SNIPPET: transaction
}
// START SNIPPET: shutdownHook
private static void registerShutdownHook( final GraphDatabaseService graphDb )
{
// Registers a shutdown hook for the Neo4j instance so that it
// shuts down nicely when the VM exits (even if you "Ctrl-C" the
// running application).
Runtime.getRuntime().addShutdownHook( new Thread()
{
#Override
public void run()
{
graphDb.shutdown();
}
} );
}
// END SNIPPET: shutdownHook
}
I do NOT want to use anything else, except the neo4j's built in browser.
How should I proceed?
Thanks in advance.
You must shut down the server, then create your data, then start the server again, you cannot use the same data directory from two database processes at the same time.
Your DB_PATH is also wrong, you can't have a star in there.