I am new to Ehcache and Slf4j .I am using ehcache-2.6.6
I have used
slf4j-api-1.6.1 jar
slf4j-jdk14-1.6.1 jar
When i extracted ehcache-2.6.6-distribution.tar these two jars were in folder lib .
This is my ehcache.xml
<?xml version="1.0" encoding="UTF-8"?>
<ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="ehcache.xsd"
updateCheck="true" monitoring="autodetect"
dynamicConfig="true">
<diskStore path="java.io.tmpdir"/>
<defaultCache
maxEntriesLocalHeap="10000"
eternal="false"
timeToIdleSeconds="120"
timeToLiveSeconds="120"
diskSpoolBufferSizeMB="30"
maxEntriesLocalDisk="10000000"
diskExpiryThreadIntervalSeconds="120"
memoryStoreEvictionPolicy="LRU"
statistics="false">
<persistence strategy="localTempSwap"/>
</defaultCache>
<cache name="myCache1"
maxEntriesLocalHeap="10000"
maxEntriesLocalDisk="1000"
eternal="false"
diskSpoolBufferSizeMB="20"
timeToIdleSeconds="300"
timeToLiveSeconds="600"
memoryStoreEvictionPolicy="LFU"
transactionalMode="off">
<persistence strategy="localTempSwap"/>
</cache>
</ehcache>
This is my code
package cache;
import java.util.ArrayList;
import java.util.List;
import net.sf.ehcache.CacheManager;
import net.sf.ehcache.Ehcache;
import net.sf.ehcache.Element;
public class EhcacheWrapper {
private static CacheManager cacheManager;
private static final String CACHE_NAME = "myCache1";
private static Ehcache getCache(String cacheName) {
if (cacheManager == null) {
cacheManager = CacheManager.create("ehcache.xml");
}
Ehcache cache = null;
if (cacheManager != null) {
cache = cacheManager.getEhcache(cacheName);
}
return cache;
}
public static <T> List<T> getListFromCache( String cacheName, String key, CacheCreation<T> cacheCreation){
List<T> all = new ArrayList<T>();
Ehcache cache = getCache(cacheName);
Element element = null;
if(cache!=null){
element = cache.get(key);
}
if(element==null){
System.out.println(" : CacheUtil.getListFromCache() : the element '"+key+"' has not been found in the cache ---> get the original data.");
all = cacheCreation.getAll();
cache.put(new Element(key, all));
System.out.println(" : CacheUtil.getListFromCache() : the original data for the element '"+key+"' has been added in the cache.");
}else{
System.out.println(" : CacheUtil.getListFromCache() : the element '"+key+"' has been found in the cache.");
all = (List<T>) element.getObjectValue();
}
return all;
}
public List<String> getAllData1(){
return getListFromCache( CACHE_NAME, "data1", new CacheCreation<String>(){
#Override
public List<String> getAll(){
System.out.println(" : UseCaseClass.getAllData1() : the target original method is called to get the values.");
List<String> list = new ArrayList<String>();
list.add("data1-value1");
list.add("data1-value2");
list.add("data1-value3");
list.add("data1-value4");
return list;
}
});
}
public static void main(String[] args) {
EhcacheWrapper wrappertest=new EhcacheWrapper();
wrappertest.getAllData1();
try {
Thread.sleep(1500);
} catch (InterruptedException e) {
}
wrappertest.getAllData1();
try {
Thread.sleep(1500);
} catch (InterruptedException e) {
}
wrappertest.getAllData1();
try {
Thread.sleep(1500);
} catch (InterruptedException e) {
}
}
}
When i run program i am getting following output
SLF4J: The requested version 1.6 by your slf4j binding is not compatible with [1.5.5, 1.5.6, 1.5.7, 1.5.8, 1.5.9, 1.5.10, 1.5.11]
SLF4J: See http://www.slf4j.org/codes.html#version_mismatch for further details.
May 15, 2013 1:52:36 PM net.sf.ehcache.DiskStorePathManager resolveAndLockIfNeeded
WARNING: diskStorePath 'C:\Users\toshiba\AppData\Local\Temp' is already used by an existing CacheManager either in the same VM or in a different process.
The diskStore path for this CacheManager will be set to C:\Users\toshiba\AppData\Local\Temp\ehcache_auto_created3199473242323720768diskstore.
To avoid this warning consider using the CacheManager factory methods to create a singleton CacheManager or specifying a separate ehcache configuration (ehcache.xml) for each CacheManager instance.
: CacheUtil.getListFromCache() : the element 'data1' has not been found in the cache ---> get the original data.
: UseCaseClass.getAllData1() : the target original method is called to get the values.
: CacheUtil.getListFromCache() : the original data for the element 'data1' has been added in the cache.
: CacheUtil.getListFromCache() : the element 'data1' has been found in the cache.
: CacheUtil.getListFromCache() : the element 'data1' has been found in the cache.
Though i am getting expected output but there is error in beginning saying :
SLF4J: The requested version 1.6 by your slf4j binding is not compatible with [1.5.5, 1.5.6, 1.5.7, 1.5.8, 1.5.9, 1.5.10, 1.5.11]
SLF4J: See http://www.slf4j.org/codes.html#version_mismatch for further details.
May 15, 2013 1:52:36 PM net.sf.ehcache.DiskStorePathManager resolveAndLockIfNeeded
WARNING: diskStorePath 'C:\Users\toshiba\AppData\Local\Temp' is already used by an existing CacheManager either in the same VM or in a different process.
The diskStore path for this CacheManager will be set to C:\Users\toshiba\AppData\Local\Temp\ehcache_auto_created3199473242323720768diskstore.
To avoid this warning consider using the CacheManager factory methods to create a singleton CacheManager or specifying a separate ehcache configuration (ehcache.xml) for each CacheManager instance.
I look in
slf4j-api version does not match that of the binding
for error but i could not get error for this
I saw similar error here EhCache: Simple Program not working
But it is taking about distributed cache.
For code i took reference from
Java/Ehcache: A simple example of use of Ehcache 2.6.2
Any help please why i am getting error in beginning?
As the warning says
To avoid this warning consider using the CacheManager factory methods to create a singleton CacheManager or specifying a separate ehcache configuration (ehcache.xml) for each CacheManager instance.
The following line using SingletonEhCacheProvider may fix your issue
<property name="hibernate.cache.provider_class">net.sf.ehcache.hibernate.SingletonEhCacheProvider</property>
Related
I have a docker-compose setup to start my SpringBoot application and a MySQL database. If the database starts first, then my application can connect successfully. But if my application starts first, no database exists yet, so the application throws the following exception and exits:
app_1 | 2018-05-27 14:15:03.415 INFO 1 --- [ main]
com.zaxxer.hikari.HikariDataSource : HikariPool-1 - Starting...
app_1 | 2018-05-27 14:15:06.770 ERROR 1 --- [ main]
com.zaxxer.hikari.pool.HikariPool : HikariPool-1 - Exception during pool initialization
app_1 | com.mysql.jdbc.exceptions.jdbc4.CommunicationsException:
Communications link failure
I could edit my docker-compose file to make sure the database is always up before the application starts up, but I want the application to be able to handle this case on its own, and not immediately exit when it cannot reach the database address.
There are ways to configure the datasource in the application.properties file to make the application reconnect to the database, as answered here and here. But that doesn't work for a startup connection to the datasource.
How can I make my SpringBoot application retry the connection at startup to the database at a given interval until it successfully connects to the database?
Set HikariCP's initializationFailTimeout property to 0 (zero), or a negative number. As documented here:
⌚initializationFailTimeout
This property controls whether the pool will "fail fast" if the pool cannot be seeded with an initial connection successfully. Any positive number is taken to be the number of milliseconds to attempt to acquire an initial connection; the application thread will be blocked during this period. If a connection cannot be acquired before this timeout occurs, an exception will be thrown. This timeout is applied after the connectionTimeout period. If the value is zero (0), HikariCP will attempt to obtain and validate a connection. If a connection is obtained, but fails validation, an exception will be thrown and the pool not started. However, if a connection cannot be obtained, the pool will start, but later efforts to obtain a connection may fail. A value less than zero will bypass any initial connection attempt, and the pool will start immediately while trying to obtain connections in the background. Consequently, later efforts to obtain a connection may fail. Default: 1
There is an alternative way to do this, which doesn't rely on a specific Connection Pool library or a specific database. Note that you will need to use spring-retry to achieve the desired behaviour with this approach
First you need to add spring-retry to your dependencies :
<dependency>
<groupId>org.springframework.retry</groupId>
<artifactId>spring-retry</artifactId>
<version>${spring-retry.version}</version>
</dependency>
Then you can create a decorator over DataSource that will extends AbstractDataSource like bellow :
#Slf4j
#RequiredArgsConstructor
public class RetryableDataSource extends AbstractDataSource {
private final DataSource dataSource;
#Override
#Retryable(maxAttempts = 5, backoff = #Backoff(multiplier = 1.3, maxDelay = 10000))
public Connection getConnection() throws SQLException {
log.info("getting connection ...");
return dataSource.getConnection();
}
#Override
#Retryable(maxAttempts = 5, backoff = #Backoff(multiplier = 2.3, maxDelay = 10000))
public Connection getConnection(String username, String password) throws SQLException {
log.info("getting connection by username and password ...");
return dataSource.getConnection(username, password);
}
}
Then you will need to inject this custom DataSource decorator into Spring context by creating a custom BeanPostProcessor :
#Slf4j
#Order(value = Ordered.HIGHEST_PRECEDENCE)
#Component
public class RetryableDatabasePostProcessor implements BeanPostProcessor {
#Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
if(bean instanceof DataSource) {
log.info("-----> configuring a retryable datasource for beanName = {}", beanName);
return new RetryableDataSource((DataSource) bean);
}
return bean;
}
#Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
return bean;
}
}
Last but not least you will need to enable Spring retry by adding #EnableRetry annotation to spring main class, example :
#EnableRetry
#SpringBootApplication
public class RetryableDbConnectionApplication {
public static void main(String[] args) {
SpringApplication.run(RetryableDbConnectionApplication.class, args);
}
}
I have tomcat memory leak issue when stop/redeploy application. It says The following web applications were stopped (reloaded, undeployed), but their
classes from previous runs are still loaded in memory, thus causing a memory
leak (use a profiler to confirm):/test-1.0-SNAPSHOT
MySQL connector driver located in Tomcat/lib folder.
I can reproduce this issue in both: Tomcat 7/8. Also tried MS SQL database with "net.sourceforge.jtds.*" driver but didn't help.
Please find below project files. Project only creates 1 table in DB.
build.gradle
group 'com.test'
version '1.0-SNAPSHOT'
apply plugin: 'java'
apply plugin: 'war'
sourceCompatibility = 1.8
repositories {
mavenCentral()
}
dependencies {
compile group: 'org.hibernate', name: 'hibernate-entitymanager', version: '5.2.10.Final'
compile group: 'org.springframework.data', name: 'spring-data-jpa', version: '1.11.4.RELEASE'
compile group: 'org.springframework', name: 'spring-webmvc', version: '4.3.9.RELEASE'
providedCompile 'javax.servlet:javax.servlet-api:3.1.0'
providedCompile group: 'mysql', name: 'mysql-connector-java', version: '5.1.6'
compile group: 'commons-dbcp', name: 'commons-dbcp', version: '1.4'
}
ApplicationConfig.java
#Configuration
#Import({JPAConfiguration.class})
#EnableWebMvc
public class ApplicationConfig {}
JPAConfiguration.java
#Configuration
#EnableJpaRepositories("com.test.dao")
#EnableTransactionManagement
public class JPAConfiguration {
#Bean
public EntityManagerFactory entityManagerFactory() {
LocalContainerEntityManagerFactoryBean factory = new LocalContainerEntityManagerFactoryBean();
factory.setJpaVendorAdapter(new HibernateJpaVendorAdapter());
factory.setPackagesToScan("com.test.model");
factory.setDataSource(restDataSource());
factory.setJpaPropertyMap(getPropertyMap());
factory.afterPropertiesSet();
return factory.getObject();
}
#Bean(destroyMethod = "close")
public DataSource restDataSource() {
BasicDataSource dataSource = new BasicDataSource();
dataSource.setDriverClassName("com.mysql.jdbc.Driver");
dataSource.setUrl("jdbc:mysql://localhost:3306/test");
dataSource.setUsername("test");
dataSource.setPassword("test");
return dataSource;
}
private Map<String, String> getPropertyMap() {
Map<String, String> hibernateProperties = new HashMap<>();
hibernateProperties.put("hibernate.hbm2ddl.auto", "update");
hibernateProperties.put("hibernate.show_sql", "true");
hibernateProperties.put("hibernate.format_sql", "true");
hibernateProperties.put("hibernate.dialect", "org.hibernate.dialect.MySQL5InnoDBDialect");
return hibernateProperties;
}
#Bean
public PlatformTransactionManager transactionManager() {
JpaTransactionManager txManager = new JpaTransactionManager();
txManager.setEntityManagerFactory(entityManagerFactory());
return txManager;
}
}
TestRepository.java
#Repository
public interface TestRepository extends JpaRepository<TestEntity, Long> {}
TestEntity.java
#Entity
#Table(name = "ent")
public class TestEntity {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String descript;
//equals, hashcode, toString, getters, setters
}
AppInitializer.java
public class AppInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {
private WebApplicationContext rootContext;
#Override
protected Class<?>[] getRootConfigClasses() {
return new Class[]{ApplicationConfig.class};
}
#Override
protected Class<?>[] getServletConfigClasses() {
return null;
}
#Override
protected String[] getServletMappings() {
return new String[]{"/"};
}
}
Command
jmap -histo <tomcat_pid>
shows only 2 items from project structure after tomcat stop:
com.test.config.dao.JPAConfiguration$$EnhancerBySpringCGLIB$$792cb231$$FastClassBySpringCGLIB$$45ff499c
com.test.config.dao.JPAConfiguration$$FastClassBySpringCGLIB$$10104c1e
Anyone have ideas or suggestions to fix this problem?
There are 2 memory leaks in this small project:
The problem with MySQL jdbc driver.
We have to add ContextLoaderListener to deregister jdbc driver:
Listener:
#WebListener
public class ContextListener extends ContextLoaderListener {
private final Logger log = LoggerFactory.getLogger(this.getClass());
#Override
public void contextInitialized(ServletContextEvent sce) {
log.info("-= Context started =-");
}
#Override
public void contextDestroyed(ServletContextEvent sce) {
super.contextDestroyed(sce);
log.info("-= Context destroyed =-");
try {
log.info("Calling MySQL AbandonedConnectionCleanupThread checkedShutdown");
com.mysql.cj.jdbc.AbandonedConnectionCleanupThread.uncheckedShutdown();
} catch (Exception e) {
log.error("Error calling MySQL AbandonedConnectionCleanupThread checkedShutdown {}", e);
}
ClassLoader cl = Thread.currentThread().getContextClassLoader();
Enumeration<Driver> drivers = DriverManager.getDrivers();
while (drivers.hasMoreElements()) {
Driver driver = drivers.nextElement();
if (driver.getClass().getClassLoader() == cl) {
try {
log.info("Deregistering JDBC driver {}", driver);
DriverManager.deregisterDriver(driver);
} catch (SQLException ex) {
log.error("Error deregistering JDBC driver {}", driver, ex);
}
} else {
log.info("Not deregistering JDBC driver {} as it does not belong to this webapp's ClassLoader", driver);
}
}
}
}
or if you had an access to tomcat server you can modify listener in tomcat/conf/server.xml example.
The second problem is known memory leak in jboss-logging library (link).
The memory leak has gone after we exclude this library from hibernate dependency:
build.gradle:
group 'com.test'
version '1.0-SNAPSHOT'
apply plugin: 'java'
apply plugin: 'war'
sourceCompatibility = 1.8
repositories {
mavenCentral()
}
dependencies {
compile(group: 'org.hibernate', name: 'hibernate-entitymanager', version: '5.2.10.Final') {
exclude group: 'org.jboss.logging', module: 'jboss-logging'
}
compile group: 'org.springframework.data', name: 'spring-data-jpa', version: '1.11.4.RELEASE'
compile group: 'org.springframework', name: 'spring-webmvc', version: '4.3.9.RELEASE'
providedCompile 'javax.servlet:javax.servlet-api:3.1.0'
providedCompile group: 'mysql', name: 'mysql-connector-java', version: '8.0.11'
compile group: 'org.slf4j', name: 'slf4j-api', version: '1.7.25'
compile group: 'org.slf4j', name: 'slf4j-simple', version: '1.7.25'
}
then build jar from repo and added to tomcat /lib folder.
The issue with jboss-logging probably fixed in Java 9 (pull request link).
Short answer - hopefully the same problem for you...
Those two com.test.config.dao.JPAConfiguration$$...CGLIB$$... classes were being referenced indirectly by the Abandoned connection cleanup thread in MySQL:
20-Jun-2018 21:25:22.987 WARNING [localhost-startStop-1] org.apache.catalina.loader.WebappClassLoaderBase.clearReferencesThreads The web application [test-1.0-SNAPSHOT] appears to have started a thread named [Abandoned connection cleanup thread] but has failed to stop it. This is very likely to create a memory leak. Stack trace of thread:
java.lang.Object.wait(Native Method)
java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:143)
com.mysql.cj.jdbc.AbandonedConnectionCleanupThread.run(AbandonedConnectionCleanupThread.java:43)
The following answer enabled me to resolve the problem. E.g. in tomcat/conf/server.xml, look for the JreMemoryLeakPreventionListener line and replace it with this:
<Listener className="org.apache.catalina.core.JreMemoryLeakPreventionListener"
classesToInitialize="com.mysql.jdbc.Driver" />
This forces the MySQL JDBC driver, and its cleanup thread, to be loaded outside the classloader for the web application. This means the cleanup thread won't hold a reference to the webapp classloader as its context class loader.
Expanded answer - how to trace the leak in your environment...
Hopefully the above is all you need - it was enough to reproduce and solve the problem against https://github.com/egotovko/tomcat-leak
However there are many other causes of a leaked reference to a web application that can stop it undeploying. E.g. other threads still running (Tomcat is good at warning about these) or references from outside the web application.
To properly trace the cause, you can chase the reference in a heap dump. If this is not familiar, you can get a heap dump from jmap -dump:file=dump.hprof <pid>, or by directly connecting from such as jvisualvm (also included in the JDK).
With the heap dump open in jvisualvm:
Select the Classes button for the heap dump
Sort the list of classes by name
Look for classes in the web application - e.g. com.test.config.dao.JPAConfiguration$$EnhancerBySpringCGLIB$$ in this example
This should be showing with an instance count of 2 or so
Double click to show these in the Instances View
In the References pane for one of these instances, right click and Show Nearest GC Root
E.g. for that Abandoned connection cleanup thread in MySQL:
Note how the AbandonedConnectionCleanupThread has a contextClassLoader, which is the ParallelWebappClassLoader for the web application. Tomcat needs to be able to release the class loader to undeploy the web application.
Once you've tracked down what's holding the reference, it's then normally a case of investigating how better to configure that library in Tomcat, or perhaps someone else has seen that memory leak. It's also not uncommon to have to repeat the exercise, when there are several references to clear up.
We have upgrade our application to use CDI beans. This change was very smooth when we are deploying our application on Wildfly 10.x, but when we tried to deploy the same application on Websphere Classic and Liberty some problems came up.
We have look for several questions already posted here, like this, this, this or this, but none of the answers were able to solve our problem.
On my localhost I am using Websphere Liberty Profile with webProfile-7.0, meaning CDI-1.2, EL-3.0, JSF-2.2 and servlet-3.1.
Our application also uses Primefaces 6.0.
The problem occurs on a phaseListener. On it, we are injecting a Bean annotated with both #Named (javax.inject.Named) and #SessionScoped (javax.enterprise.context.SessionScoped).
When the injected variable is called on the phaseListener the following error is thrown.
[err] 2017-05-10 09:45:06 ERROR MWExceptionHandler:139 - A server exception occurred
org.jboss.weld.context.ContextNotActiveException: WELD-001303: No active contexts for scope type javax.enterprise.context.SessionScoped
at org.jboss.weld.manager.BeanManagerImpl.getContext(BeanManagerImpl.java:691)
at org.jboss.weld.bean.ContextualInstanceStrategy$DefaultContextualInstanceStrategy.getIfExists(ContextualInstanceStrategy.java:89)
at org.jboss.weld.bean.ContextualInstanceStrategy$CachingContextualInstanceStrategy.getIfExists(ContextualInstanceStrategy.java:164)
at org.jboss.weld.bean.ContextualInstance.getIfExists(ContextualInstance.java:63)
at org.jboss.weld.bean.proxy.ContextBeanInstance.getInstance(ContextBeanInstance.java:83)
at org.jboss.weld.bean.proxy.ProxyMethodHandler.getInstance(ProxyMethodHandler.java:125)
at web.frmwrk.mgbean.WebSession$Proxy$_$$_WeldClientProxy.getLocale(Unknown Source)
at web.frmwrk.application.LocaleFaceletViewHandler.calculateLocale(LocaleFaceletViewHandler.java:43)
at javax.faces.application.ViewHandlerWrapper.calculateLocale(ViewHandlerWrapper.java:76)
at org.apache.myfaces.application.ResourceHandlerImpl.getLocalePrefixForLocateResource(ResourceHandlerImpl.java:715)
at org.apache.myfaces.application.ResourceHandlerImpl.createViewResource(ResourceHandlerImpl.java:1609)
at org.apache.myfaces.application.ResourceHandlerImpl.createViewResource(ResourceHandlerImpl.java:62)
at javax.faces.application.ResourceHandlerWrapper.createViewResource(ResourceHandlerWrapper.java:83)
at javax.faces.application.ResourceHandlerWrapper.createViewResource(ResourceHandlerWrapper.java:83)
at javax.faces.application.ResourceHandlerWrapper.createViewResource(ResourceHandlerWrapper.java:83)
at javax.faces.application.ResourceHandlerWrapper.createViewResource(ResourceHandlerWrapper.java:83)
at org.apache.myfaces.view.facelets.impl.DefaultResourceResolver.resolveUrl(DefaultResourceResolver.java:53)
at org.apache.myfaces.view.facelets.impl.DefaultResourceResolver.resolveUrl(DefaultResourceResolver.java:39)
at org.apache.myfaces.view.facelets.FaceletViewDeclarationLanguage.viewExists(FaceletViewDeclarationLanguage.java:325)
at org.apache.myfaces.shared.application.DefaultViewHandlerSupport.checkResourceExists(DefaultViewHandlerSupport.java:573)
at org.apache.myfaces.shared.application.DefaultViewHandlerSupport.handleSuffixMapping(DefaultViewHandlerSupport.java:507)
at org.apache.myfaces.shared.application.DefaultViewHandlerSupport.calculateViewId(DefaultViewHandlerSupport.java:113)
at org.apache.myfaces.application.ViewHandlerImpl.deriveLogicalViewId(ViewHandlerImpl.java:122)
at javax.faces.application.ViewHandlerWrapper.deriveLogicalViewId(ViewHandlerWrapper.java:112)
at javax.faces.application.ViewHandlerWrapper.deriveLogicalViewId(ViewHandlerWrapper.java:112)
at javax.faces.application.ViewHandlerWrapper.deriveLogicalViewId(ViewHandlerWrapper.java:112)
at javax.faces.application.ViewHandlerWrapper.deriveLogicalViewId(ViewHandlerWrapper.java:112)
at org.apache.myfaces.lifecycle.RestoreViewExecutor.execute(RestoreViewExecutor.java:225)
at org.apache.myfaces.lifecycle.LifecycleImpl.executePhase(LifecycleImpl.java:196)
at org.apache.myfaces.lifecycle.LifecycleImpl.execute(LifecycleImpl.java:143)
at javax.faces.webapp.FacesServlet.service(FacesServlet.java:198)
at com.ibm.ws.webcontainer.servlet.ServletWrapper.service(ServletWrapper.java:1290)
at com.ibm.ws.webcontainer.servlet.ServletWrapper.handleRequest(ServletWrapper.java:778)
at com.ibm.ws.webcontainer.servlet.ServletWrapper.handleRequest(ServletWrapper.java:475)
at com.ibm.ws.webcontainer.filter.WebAppFilterChain.invokeTarget(WebAppFilterChain.java:148)
at com.ibm.ws.webcontainer.filter.WebAppFilterChain.doFilter(WebAppFilterChain.java:79)
at com.ibm.ws.webcontainer.filter.WebAppFilterManager.doFilter(WebAppFilterManager.java:1021)
at com.ibm.ws.webcontainer.filter.WebAppFilterManager.invokeFilters(WebAppFilterManager.java:1143)
at com.ibm.ws.webcontainer.webapp.WebAppRequestDispatcher.dispatch(WebAppRequestDispatcher.java:1381)
at com.ibm.ws.webcontainer.webapp.WebAppRequestDispatcher.include(WebAppRequestDispatcher.java:541)
at com.ibm.ws.webcontainer.webapp.WebApp.sendError(WebApp.java:4265)
at com.ibm.ws.webcontainer.webapp.WebApp.handleException(WebApp.java:5031)
at com.ibm.ws.webcontainer.webapp.WebApp.handleRequest(WebApp.java:5011)
at com.ibm.ws.webcontainer31.osgi.webapp.WebApp31.handleRequest(WebApp31.java:525)
at com.ibm.ws.webcontainer.osgi.DynamicVirtualHost$2.handleRequest(DynamicVirtualHost.java:315)
at com.ibm.ws.webcontainer.WebContainer.handleRequest(WebContainer.java:1014)
at com.ibm.ws.webcontainer.osgi.DynamicVirtualHost$2.run(DynamicVirtualHost.java:280)
at com.ibm.ws.http.dispatcher.internal.channel.HttpDispatcherLink$TaskWrapper.run(HttpDispatcherLink.java:967)
at com.ibm.ws.http.dispatcher.internal.channel.HttpDispatcherLink.wrapHandlerAndExecute(HttpDispatcherLink.java:359)
at com.ibm.ws.http.dispatcher.internal.channel.HttpDispatcherLink.ready(HttpDispatcherLink.java:318)
at com.ibm.ws.http.channel.internal.inbound.HttpInboundLink.handleDiscrimination(HttpInboundLink.java:471)
at com.ibm.ws.http.channel.internal.inbound.HttpInboundLink.handleNewRequest(HttpInboundLink.java:405)
at com.ibm.ws.http.channel.internal.inbound.HttpInboundLink.processRequest(HttpInboundLink.java:285)
at com.ibm.ws.http.channel.internal.inbound.HttpICLReadCallback.complete(HttpICLReadCallback.java:66)
at com.ibm.ws.tcpchannel.internal.WorkQueueManager.requestComplete(WorkQueueManager.java:504)
at com.ibm.ws.tcpchannel.internal.WorkQueueManager.attemptIO(WorkQueueManager.java:574)
at com.ibm.ws.tcpchannel.internal.WorkQueueManager.workerRun(WorkQueueManager.java:929)
at com.ibm.ws.tcpchannel.internal.WorkQueueManager$Worker.run(WorkQueueManager.java:1018)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
at java.lang.Thread.run(Thread.java:745)
[ERROR ] SRVE0777E: Exception thrown by application class 'javax.faces.webapp.FacesServlet.service:230'
javax.servlet.ServletException: WELD-001303: No active contexts for scope type javax.enterprise.context.SessionScoped
at javax.faces.webapp.FacesServlet.service(FacesServlet.java:230)
at [internal classes]
Caused by: org.jboss.weld.context.ContextNotActiveException: WELD-001303: No active contexts for scope type javax.enterprise.context.SessionScoped
at org.jboss.weld.manager.BeanManagerImpl.getContext(BeanManagerImpl.java:691)
at [internal classes]
at web.frmwrk.mgbean.WebSession$Proxy$_$$_WeldClientProxy.getLocale(Unknown Source)
at web.frmwrk.application.LocaleFaceletViewHandler.calculateLocale(LocaleFaceletViewHandler.java:43)
at javax.faces.application.ViewHandlerWrapper.calculateLocale(ViewHandlerWrapper.java:76)
... 1 more
Here is Session Scoped bean we wish to inject
#Named("ws")
#SessionScoped
public class WebSession extends LoggableBean {
private static final long serialVersionUID = 5L;
#Inject
protected WebApplication wa;
/** True if session originates from a trusted logon */
private boolean trusted = false;
/**
* Current user, null if not logged in (this may be a simulated user token if {#link #simulateUser(int)} was called
* before.
*/
private ISofTokenType userToken;
/**
* Original login user (identical to userToken if not simulating another user
*/
private ISofTokenType loginUserToken;
/** Current locale of the websession. */
private Locale locale;
/** The policy rules resolver for this session */
private transient PolicyResolver policy;
#Inject
protected Config config;
#Inject
protected WebPaths path;
#Inject
protected WebApplicationStore waStore;
#PostConstruct
protected void init() {
try {
setLocale(LocaleUtils.getDefaultLanguage().getCode());
} catch (ConfigurationException ex) {
// Fallback to default language in config.xml
getLog().error(ex);
locale = FacesContext.getCurrentInstance().getApplication().getDefaultLocale();
}
}
/**
* Check if the currentRelease session is linked with a logged in user or if the visitor is a guest.
*
* #return True if the user is logged in, false otherwise.
*/
public boolean isLoggedIn() {
return userToken != null;
}
}
And here the phaseListener
public class PolicyController implements PhaseListener {
private static final long serialVersionUID = 2189917635371117541L;
private static final Log log = LogFactory.getLog(PolicyController.class);
private static final String VALIDATION_ERROR_DEFAULT_KEY = "validation_error_default";
private static final String COMPONENT_ATTRIBUTE_RENDERED_MODIFIED_BY_RULE = "rendered-modified-by-policy";
private static enum PhaseMoment {
BEFORE, AFTER
};
#Inject
private WebSession ws;
public void beforePhase(PhaseEvent event) {
if (!FacesHelper.getConfig().getBoolean(Properties.POLICY_CONTROLLER_ENABLED, true)) {
if (event.getPhaseId() == PhaseId.RENDER_RESPONSE) log.debug("Policy is disabled");
return;
}
if ((event.getPhaseId() == PhaseId.RENDER_RESPONSE || event.getPhaseId() == PhaseId.PROCESS_VALIDATIONS)
&& ws.isLoggedIn()) { // <- Error happens here
// Apply the rules...
FacesContext fc = event.getFacesContext();
log.debug("Run PolicyController before " + event.getPhaseId() + " (viewroot has "
+ fc.getViewRoot().getChildCount() + " direct children)");
traverseComponent(fc, fc.getViewRoot(), event.getPhaseId(), PhaseMoment.BEFORE);
}
}
public void afterPhase(PhaseEvent event) {
if (!FacesHelper.getConfig().getBoolean(Properties.POLICY_CONTROLLER_ENABLED, true)) {
return;
}
if ((event.getPhaseId() == PhaseId.PROCESS_VALIDATIONS || event.getPhaseId() == PhaseId.RESTORE_VIEW)
&& ws.isLoggedIn()) { // <- Error happens here
FacesContext fc = event.getFacesContext();
log.debug("Run PolicyController after " + event.getPhaseId() + " (viewroot has "
+ fc.getViewRoot().getChildCount() + " direct children)");
traverseComponent(fc, fc.getViewRoot(), event.getPhaseId(), PhaseMoment.AFTER);
}
}
}
I've also tried adding
FacesContext context = event.getFacesContext();
WebSession webSession = context.getApplication().evaluateExpressionGet(context, "#{ws}", WebSession.class);
before the if statement and use webSession instead of ws, but got the same error.
Once again, I would like to point that this is working fine in Wildfly, which lead us to assume we are implementing the code correctly. Also, we are sure we are using Java 8 and the server supports JEE7, so, from all the places we've looked we were assuming this should be something to be supported on our version of Websphere.
We have the exact same problem when deploying the app on Websphere Classic 9.0.
The only difference we find so far is that Websphere uses Myfaces while Wildfly uses Mojarra. Can this be some kind of bug in Myfaces? Is there any specific configuration or code we need to use to support this kind of things?
If you need more info about our implementation that may help to figure out the cause of this, just let me know what.
Following up on this issue 4 years too late, but, in case others find it, the solution should be to set deferServletRequestListenerDestroyOnError as true on WebSphere.
Or just add this to the server.xml if you're on Liberty:
<webContainer deferServletRequestListenerDestroyOnError="true" />
https://www.ibm.com/support/pages/apar/PI26908
A explanation of this property can be found here: https://github.com/OpenLiberty/open-liberty/issues/18281#issuecomment-1353399402
I have been using the following bit of code in a servlet to locate a session backing bean (as suggested by BalusC) without problems until recently. Now it only works on Internet Explorer. Chrome and Firefox appear to be getting a totally new backing bean rather than the original backing bean. When calling functions in the backing bean, it falls over with null pointer errors for objects in the backing bean that were definitely initialized in the original.
FacesContext facesContext = FacesUtil.getFacesContext(req, res);
ProductSelection productSelection = (ProductSelection) facesContext.getApplication().evaluateExpressionGet(facesContext, "#{productSelection}", ProductSelection.class);
if(productSelection.getProductType() == null)
{
System.out.println("Sevlet: product type is NULL; did not get the original backing bean");
}
else
{
System.out.println("Sevlet: product type is: " + productSelection.getProductType().getProductTypeName());
}
It is a while since I tested this code and there have been several updates to Java but I'm not sure if these are the cause; I have changed something in my configuration or Chrome and Firefox have changed something in their code (unlikely). Is anyone else having similar problems? I am at a loss as to where to go from here, as there does not appear to be any errors associated with not finding the backing bean and my debugging skills for the java lib code are not that great (they don't comment their code very well and it is hard to follow); any suggestions would be greatly appreciated.
I am using Netbeans 7.01, JSF 2.0, Glassfish 3.1, and a Derby database. I tested it on my tower and laptop and it is doing it on both (Win XP and Win 7). The JRE is 7 update 40 build 1.7.0_40-b43. JDK is 1.6.0_04. Chrome version is 29.0.1547.76 m. Firefox is 23.0.1. Internet Explorer is 8.0.6001.18702.
The FacesUtil is slightly different to BalusC's code (but it was working fine):
package searchselection;
import javax.faces.FactoryFinder;
import javax.faces.component.UIViewRoot;
import javax.faces.context.FacesContext;
import javax.faces.context.FacesContextFactory;
import javax.faces.lifecycle.Lifecycle;
import javax.faces.lifecycle.LifecycleFactory;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
// By BalusC http://balusc.blogspot.com
// Utility to get the FacesContext.
// Used by the CriteriaServlet to get the backing bean when the user submits a customised
// search criteria object.
public class FacesUtil
{
// Getters -----------------------------------------------------------------
//
public static FacesContext getFacesContext(ServletRequest request, ServletResponse response)
{
// Get current FacesContext.
FacesContext facesContext = FacesContext.getCurrentInstance();
// Check current FacesContext.
if (facesContext == null)
{
// Create new Lifecycle.
LifecycleFactory lifecycleFactory = (LifecycleFactory) FactoryFinder.getFactory(FactoryFinder.LIFECYCLE_FACTORY);
Lifecycle lifecycle = lifecycleFactory.getLifecycle(LifecycleFactory.DEFAULT_LIFECYCLE);
// Create new FacesContext.
FacesContextFactory contextFactory = (FacesContextFactory) FactoryFinder.getFactory(FactoryFinder.FACES_CONTEXT_FACTORY);
facesContext = contextFactory.getFacesContext(
request.getServletContext(), request, response, lifecycle);
// Create new View.
UIViewRoot view = facesContext.getApplication().getViewHandler().createView(
facesContext, "");
facesContext.setViewRoot(view);
// Set current FacesContext.
FacesContextWrapper.setCurrentInstance(facesContext);
}
return facesContext;
}
// Helpers -----------------------------------------------------------------
// Wrap the protected FacesContext.setCurrentInstance() in a inner class.
private static abstract class FacesContextWrapper extends FacesContext
{
protected static void setCurrentInstance(FacesContext facesContext)
{
FacesContext.setCurrentInstance(facesContext);
}
}
}
Kind thanks in advance...
Work-a-round: The session Id is changing on Firefox and Chrome when the servlet is called from the applet, for some reason. I ended up storing the session ID and setting it on the HttpURLConnection connection to the servlet, which forces the servlet to get the correct backing bean.
In the productSelection backing bean:
private String sessionID = ""; // With getter
.
.
.
FacesContext facesContext = FacesContext.getCurrentInstance();
HttpSession session = (HttpSession) facesContext.getExternalContext().getSession(false);
sessionID = session.getId();
On the web page containing the applet I am using a javascript function to wait until the applet is fully loaded before telling it to load a criteria file, which will be modified by the user and then sent back to the backing bean for processing. I have simply passed the session ID along with the criteria file to the applet:
<SCRIPT language="javascript">
function waitUntilLoaded()
{
if (document.criteriaApplet.isActive())
{
var object = document.getElementById ("criteriaApplet");
criteriaApplet.loadCriteriaFile((object.codeBase + "#{productSelection.productUsage.searchCriteriaObjectUrl}"), "#{productSelection.sessionID}");
}
else
{
settimeout(waitUntilLoaded(),500)
}
}
</SCRIPT>
In the applet button code, to submit the modified criteria file back to the backing bean via the servelet, I added the session ID to the HttpURLConnection connection:
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.setDoInput(true);
connection.setDoOutput(true);
connection.setUseCaches(false);
connection.setRequestMethod("POST");
connection.setRequestProperty("Content-Type", "application/x-java-serialized-object");
connection.setRequestProperty("Cookie","JSESSIONID=" + sessionID);
ObjectOutputStream out = new ObjectOutputStream(connection.getOutputStream());
out.writeObject(searchSubmitObject);
out.flush();
out.close();
I am trying to use unity to automatically inject a datacontext on my repository using a new instance each time.., my idea is the ensure that each time a new datacontext is injected
Currently its failing on creating the repository, i think it can't resolve MyDataContext
Before creating a constructor on "the repository" (see below) to take in the DataContext on my repository everything worked but now its failing..
I currently have this setup in my unity container which i create in global.asax, i have also registered the type MyDataContext which is standard DataContext
container = new UnityContainer();
Container.RegisterType<MyDataContext, MyDataContext>()
.RegisterType<IOfficeRepository, OfficeRepository>()
.RegisterType<IOfficeService, OfficeService>();
basically i have a service that calls the repository like so
public class OfficeService : IOfficeService
{
IOfficeRepository repository = null;
public OfficeService(IOfficeRepository repository)
{
this.repository = repository;
if (this.repository == null)
throw new InvalidOperationException("Repository cannot be null");
}
here is my repository
public class OfficeRepository : IOfficeRepository
{
private MyDataContext db;
public OfficeRepository (MyDataContext dataContext)
{
this.db = dataContext;
}
EDIT
I almost forgot i am doing this to create the service
officeService = Bootstrapper.Container.Resolve<IOfficeService>();
EDIT - THE ERROR BEING GENERATED
Resolution of the dependency failed, type = "MarkSmith.IOfficeService", name = "".
Exception message is: The current build operation (build key Build
Key[MarkSmith.OfficeService, null]) failed: The parameter repository could not be
resolved when attempting to call constructor
MarkSmith.OfficeService(MarkSmith.IOfficeRepository repository). (Strategy type BuildPlanStrategy, index 3)
EDIT - REMOVING Constructor on repository works
It is something to do with the datacontext because if i remove the constrcutor on the repository that takes a DataContext then all works, but of course i need it to accept a DataContext to be able to inject a "NEW" datacontext each time
public class OfficeRepository : IOfficeRepository
{
private MyDataContext db new MyDataContext(); // CHANGE
//public OfficeRepository (MyDataContext dataContext)
//{
//this.db = dataContext;
//}
EDIT - ACTUAL ERROR
After digging deeper i have found this error ....
The type MyDataContext has multiple constructors of length 2.
Unable to disambiguate. (Strategy type DynamicMethodConstructorStrategy, index 0)
(Strategy type BuildPlanStrategy, index 3)
EDIT - TEST TO RESOLVE THE DATACONTEXT with 1 line of code
This also fails with the same error as above - multiple constructors
MyDataContext test = Bootstrapper.Container.Resolve<MyDataContext >();
EDIT - ALL CONSTRUCTORS ON MY DATACONTEXT
These were created by an exernal util but all should be well..
[System.Diagnostics.DebuggerNonUserCode]
public MyDataContext()
: base(ConnectionString, mappingCache)
{
OnCreated();
}
[System.Diagnostics.DebuggerNonUserCode]
public MyDataContext(string connection)
: base(connection, mappingCache)
{
OnCreated();
}
[System.Diagnostics.DebuggerNonUserCode]
public MyDataContext(System.Data.IDbConnection connection)
: base(connection, mappingCache)
{
OnCreated();
}
[System.Diagnostics.DebuggerNonUserCode]
public MyDataContext(string connection, System.Data.Linq.Mapping.MappingSource mappingSource)
: base(connection, mappingSource)
{
OnCreated();
}
[System.Diagnostics.DebuggerNonUserCode]
public MyDataContext(System.Data.IDbConnection connection, System.Data.Linq.Mapping.MappingSource mappingSource)
: base(connection, mappingSource)
{
OnCreated();
}
EDIT - To demonstrate creating the DataContext in code without Unity works 100% without issue
MyDataContext tes2t = new MyDataContext ();
I'm not sure this works, but have you tried to register MyDataContext as a component rather than a type mapping?
container.RegisterType<MyDataContext>();
instead of
container.RegisterType<MyDataContext, MyDataContext>();
EDIT based on new information
The culprit seems to be that MyDataContext has more than one constructor. This is a common issue with most DI Containers, because they need to pick and use only one. If you can remove the ambiguity by constraining MyDataContext to have only one constructor, that will probably be the simplest solution.
Otherwise, you should be able to use an InjectionConstructor instance to identify the constructor when you register the repository. Let's assume you want to use a constructor that takes a connection string as an argument:
string connectionString =
ConfigurationManager.ConnectionStrings["MyConnection"].ConnectionString;
var injectedConnectionString = new InjectionConstructor(connectionString);
container.RegisterType<MyDataContext>(injectedConnectionString);
With multiple constructors to choose from, Unity doesn't know which one to use. It will choose the one with the most arguments that can all be satisfied, but in this case there are two constructors each with two resolvable arguments.
If you don't want to couple your MyDataContext class to Unity and use the InjectionConstructor attribute as suggested by Scott (upvoted :)), you can specify the constructor that should be used at the time of registration using the fluent interface. See Configuring Constructor, Property, and Method Injection for details.
I don't see your MyDataContext constructors; but try to add the [InjectionConstructor] attribute to the one you want to use.