register infinispan cache listener in wildfly - infinispan

I have a infinispan cache defined in wildfly stanadlone.xml as shown below.
<cache-container name="dummycache" default-cache="stringCache">
<local-cache name="stringCache">
<expiration lifespan="1800000"/>
</local-cache>
</cache-container>
This cache is initialized by the infinispan running embedded in wildfly itself. I could lookup and use the cache like below.
#Resource(lookup = "java:comp/env/infinispan/stringCache")
private Cache<String, String> stringCache;
Now I would like to add listeners to get notified about the cache expired events. But the question is how do I register this listener to the infinispan cache which is completely managed by widlfly container?
I find that we can addListeners() to cache object but at what moment ? Ideally I want it be initialized when the wildfly creates the cache itself. It looks the infinspan-standalone schema does not support listener element to set it in the cache configuration. So the only other way is to inject the cache in filter or similar and call addListener() then?
Is there any neat way to do this ?

To set the scene - I am running a web app on wildfly 10, which is run in standalone mode. The cache-container config in standalone.xml is:
<cache-container name="web" default-cache="passivation" module="org.wildfly.clustering.web.infinispan">
<local-cache name="passivation">
<locking isolation="REPEATABLE_READ"/>
<transaction locking="OPTIMISTIC" mode="BATCH"/>
<file-store passivation="true" purge="false"/>
</local-cache>
<local-cache name="persistent">
<locking isolation="REPEATABLE_READ"/>
<transaction locking="OPTIMISTIC" mode="BATCH"/>
<file-store passivation="false" purge="false"/>
</local-cache>
</cache-container>
Here are my changes step by step:
Dependency to infinispan
I have added
<dependency>
<groupId>org.infinispan</groupId>
<artifactId>infinispan-core</artifactId>
<version>9.2.4.Final</version>
<scope>provided</scope>
</dependency>
web.xml
Add a resource (in my case I am trying to get the resource for the cache container web)
<resource-ref>
<res-ref-name>infinispan/cacheContainer</res-ref-name>
<lookup-name>java:jboss/infinispan/container/web</lookup-name>
</resource-ref>
I also added a servlet context listener because I want to add the cache listener on contextInitialized
<listener>
<listener-class>some.package.ContextListenerCacheAddListener</listener-class>
</listener>
jboss-deployment-structure.xml
I have added this to my WEB-INF directory of the war
<?xml version="1.0" encoding="UTF-8"?>
<jboss-deployment-structure>
<deployment>
<dependencies>
<module name="org.infinispan" />
</dependencies>
</deployment>
</jboss-deployment-structure>
Turns out that if you skip this - infinispan classes will be loaded by different class loaders (as far as I can understand)
Java code
Injecting the resource and using it to add listeners to caches
public class ContextListenerCacheAddListener implements ServletContextListener {
#Resource(name = "infinispan/cacheContainer")
CacheContainer cacheContainer;
static Logger logger = Logger.getLogger(ContextListenerCacheAddListener.class);
#Override
public void contextInitialized(ServletContextEvent servletContextEvent) {
cacheContainer.getCache("myapp.war").addListener(new MyListener("myapp.war"));
cacheContainer.getCache("passivation").addListener(new MyListener("passivation"));
cacheContainer.getCache("persistent").addListener(new MyListener("persistent"));
}
#Override
public void contextDestroyed(ServletContextEvent servletContextEvent) {
}
#Listener
public static class MyListener{
private String name;
public MyListener(String name) {
this.name = name;
}
#CacheEntryCreated
public void onCreate(CacheEntryEvent event){
logger.warn(name +" created entry "+event.getKey() );
}
#CacheEntryModified
public void onModify(CacheEntryEvent event){
logger.warn(name +" modified entry "+event.getKey());
}
#CacheEntryVisited
public void onVisited(CacheEntryEvent event){
logger.warn(name +" visited entry "+event.getKey());
}
#TransactionRegistered
public void onTransactionRegistered(TransactionRegisteredEvent event){
logger.warn(name +" registered transaction entry ");
}
#TransactionCompleted
public void onTransactionCompleted(TransactionCompletedEvent event){
logger.warn(name +" completed transaction entry ");
}
}
}
My changes are just for testing and debugging purposes to solve a different problem than yours.

Related

Weblogic Jaxws deployment - class does not support JDK1.5

WebLogic Server Version: 10.3.6.0
Spring version: 3.2.1.RELEASE
Java JDK 1.6
I am trying to deploy a Spring application as WAR that uses jaxws into a Weblogic server.
The application works well with Jetty. However when deploying(I mean starting deployed app) Weblogic following exception occurs:
Caused By: java.lang.UnsupportedOperationException: This class does not support JDK1.5
at weblogic.xml.jaxp.RegistryTransformerFactory.setFeature(RegistryTransformerFactory.java:317)
at com.sun.xml.ws.util.xml.XmlUtil.newTransformerFactory(XmlUtil.java:392)
at com.sun.xml.ws.util.xml.XmlUtil.newTransformerFactory(XmlUtil.java:400)
at com.sun.xml.ws.util.xml.XmlUtil.<clinit>(XmlUtil.java:233)
at org.jvnet.jax_ws_commons.spring.SpringService.getObject(SpringService.java:36
.
maven pom.xml
<dependency>
<groupId>com.sun.xml.ws</groupId>
<artifactId>jaxws-rt</artifactId>
<version>2.2.10</version>
</dependency>
<dependency>
<groupId>org.jvnet.jax-ws-commons.spring</groupId>
<artifactId>jaxws-spring</artifactId>
<version>1.9</version>
</dependency>
Weblogic.xml
<weblogic-web-app>
<context-root>/MyApp</context-root>
<container-descriptor>
<prefer-web-inf-classes>true</prefer-web-inf-classes>
<show-archived-real-path-enabled>true</show-archived-real-path-enabled>
</container-descriptor>
</weblogic-web-app>
It is being fixed by changing weblogic.xml
<container-descriptor>
<prefer-web-inf-classes>false</prefer-web-inf-classes>
<show-archived-real-path-enabled>true</show-archived-real-path-enabled>
<prefer-application-packages>
<package-name>com.sun.xml.ws.server.*</package-name>
</prefer-application-packages>
</container-descriptor>
And in init servlet (if you use the old style) you should change the way you acquire the context as:
private static WebApplicationContext context;
#Override
public void contextInitialized(ServletContextEvent sce) {
ServletContext sc = sce.getServletContext();
this.context = WebApplicationContextUtils.getWebApplicationContext(sc);
...
}
public static WebApplicationContext getApplicationContext(){
return context;
}
That fixes it

Arquillian - How to debug managed Wildfly container

I am using Arquillian to write black box tests for my RESTful application. I am actually capable of debug the test classes, but unable to debug my application classes. I would like to know exactly how to do that.
My arquillian.xml:
<arquillian xmlns="http://jboss.org/schema/arquillian"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://jboss.org/schema/arquillian
http://jboss.org/schema/arquillian/arquillian_1_0.xsd">
<container qualifier="jbossas-managed" default="true">
<configuration>
<property name="jbossHome">D:\desenv\arquivos\servidores\wildfly-9.0.1.Final-test</property>
<property name="allowConnectingToRunningServer">true</property>
<property name="javaVmArguments">-Dorg.apache.deltaspike.ProjectStage=IntegrationTest</property>
</configuration>
</container>
One of my test classes:
#RunAsClient
#RunWith(Arquillian.class)
public class AuthenticationBlackBoxTest extends AbstractBlackBoxTest {
#Test
public void testInvalidCredentials(#ArquillianResource URL baseURI) {
Client client = ClientBuilder.newClient();
WebTarget target = client.target(baseURI.toString()).path("api/v1/auth");
Response response = target.request(MediaType.APPLICATION_JSON)
.post(Entity.entity(new Credentials("invalid", "invalid"), MediaType.APPLICATION_JSON));
Assert.assertEquals(401, response.getStatus());
response.close();
client.close();
}
#Test
public void testValidCredentials(#ArquillianResource URL baseURI) {
Client client = ClientBuilder.newClient();
WebTarget target = client.target(baseURI.toString()).path("api/v1/auth");
Entity<Credentials> credentialsEntity = Entity.entity(new Credentials("adm#adm.com", "123"), MediaType.APPLICATION_JSON);
Response response = target.request(MediaType.APPLICATION_JSON)
.post(credentialsEntity);
Assert.assertEquals(200, response.getStatus());
response.close();
client.close();
}
}
Inside arquillian.xml for javaVmArguments element add -Xrunjdwp:transport=dt_socket,address=8787,server=y,suspend=y.
Then in your favourite IDE you have to define a new Remote Debug configuration where you specify the host(localhost), port(8787). Place your break point, then run your test and finally start the remote debug. Official doc here.

MVC 5 NHibernate Autofac, not able to see database data

I'm building an MVC5 web app connecting to a MS SQL 2008 database, so that the users can search and make changes to data stored there. I've looked at a bunch of autofac tutorials and examples, but can't seem to make any of them work.
I'm assuming my autofac configuration is the problem, because when I run the app it says my model is null. Which I think means the autofac is not connecting to the datbase.
So, in my global.asax.cs file I have the following:
protected void Application_Start()
{
#region Autofac
// Register Controllers
var builder = new ContainerBuilder();
builder.RegisterControllers(typeof(MvcApplication).Assembly); //all controllers in assembly at once ?
builder.RegisterControllers(Assembly.GetExecutingAssembly());
builder.RegisterFilterProvider();
// Set the Dependency Resolver
IContainer container = builder.Build();
DependencyResolver.SetResolver(new AutofacDependencyResolver(container));
// Register Model Binders
builder.RegisterModelBinders(typeof(MvcApplication).Assembly); //all binders in assembly at once ?
builder.RegisterModelBinderProvider();
// Register Modules
builder.RegisterModule<PersistenceModule>();
#endregion
AreaRegistration.RegisterAllAreas();
FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
RouteConfig.RegisterRoutes(RouteTable.Routes);
BundleConfig.RegisterBundles(BundleTable.Bundles);
}
I have a hibernate.cfg.xml file as
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<configSections>
<section name="hibernate-configuration" type="NHibernate.Cfg.ConfigurationSectionHandler, NHibernate" />
</configSections>
<hibernate-configuration xmlns="urn:nhibernate-configuration-2.2">
<session-factory>
<property name="connection.provider">NHibernate.Connection.DriverConnectionProvider</property>
<property name="connection.driver_class">NHibernate.Driver.SqlClientDriver</property>
<property name="connection.connection_string">Data Source=DEVSRV\SQLSERVER;Initial Catalog=tipdemo;Persist Security Info=True;User ID=admin;Password=***********</property>
<property name="dialect">NHibernate.Dialect.MsSql2008Dialect</property>
<property name="proxyfactory.factory_class">NHibernate.ByteCode.LinFu.ProxyFactoryFactory, NHibernate.ByteCode.LinFu</property>
<!--<mapping assembly="NHibernateTest"/> -->
</session-factory>
</hibernate-configuration>
</configuration>
And my PersistenceModule class is:
public class PersistenceModule : Autofac.Module
{
protected override void Load(ContainerBuilder builder)
{
if (builder == null)
throw new ArgumentException("builder", "builder is null");
base.Load(builder);
}
private ISessionFactory ConfigureDB()
{
Configuration cfg = new Configuration().Configure(System.Web.HttpContext.Current.Server.MapPath("~/Config/hibernate.cfg.xml"));
cfg.AddAssembly(typeof(Domain.General.Project).Assembly);
return cfg.BuildSessionFactory();
}
}
You can't register things in the container after it's built.
On line 11 in the sample for Application_Start you're building the container, but then after you set the DependencyResolver you're registering more stuff with the ContainerBuilder. You can't do that - you have to register everything first, then build the container as the last thing you do.
That's why it's never entering your PersistenceModule - you've already built the container, so it's not actually getting registered.
If, for some reason, you need to add registrations to an already-built container, you need to create an all new ContainerBuilder and call builder.Update(container). However, I strongly recommend you just reorder things so the container is built last rather than go the Update route if possible.

EJB #PersistenceContext EntityManager Throws NullPointerException

I'm having a problem with injecting EntityManager by using #PersistenceContext. I try to inject EntityManager in EJB class with #PersistenceContext and I always get NullPointerException.
Here is EJB class:
#Stateless
public class BookEJB {
public BookEJB(){
}
#PersistenceContext(unitName = "BookWebStorePU")
private EntityManager em;
public Book createBook(Book book) throws Exception {
System.out.println("EM: " + em);
em.persist(book);
return book;
}
public Book findBookByIsbn10(String isbn10){
Book book = new Book();
em.find(Book.class, isbn10);
return book;
}
//Other methods here
}
Here's Persistence.xml
<?xml version="1.0" encoding="UTF-8"?>
<persistence version="2.1" xmlns="http://xmlns.jcp.org/xml/ns/persistence"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/persistence
http://xmlns.jcp.org/xml/ns/persistence/persistence_2_1.xsd">
<persistence-unit name="BookWebStorePU" transaction-type="RESOURCE_LOCAL">
<provider>org.eclipse.persistence.jpa.PersistenceProvider</provider>
<exclude-unlisted-classes>false</exclude-unlisted-classes>
<validation-mode>NONE</validation-mode>
<properties>
<property name="javax.persistence.schema-generation.database.action" value="create"/>
<property name="javax.persistence.jdbc.driver" value="org.apache.derby.jdbc.EmbeddedDriver"/>
<property name="javax.persistence.jdbc.url" value="jdbc:derby://localhost:1527/BookWebStoreDB"/>
<property name="javax.persistence.jdbc.user" value="bookwebstoreadmin"/>
<property name="javax.persistence.jdbc.password" value="password"/>
<!-- Let EclipseLink create database schemas automatically -->
<property name="eclipselink.ddl-generation" value="drop-and-create-tables"/>
<property name="eclipselink.ddl-generation.output-mode" value="database"/>
</properties>
Here's my test file:
public class BookDaoTests {
private BookEJB bookDao;
private Book newBook;
#Before
public void init() {
newBook = new Book();
newBook.setName("Flying Cow");
newBook.setDescription("Super cool story about flying cow");
newBook.setAuthor("Me");
newBook.setIsbn10("0123456789");
newBook.setIllustrations(true);
newBook.setPublishYear(2013);
newBook.setNumberOfPages(1567);
newBook.setQuantity(58);
bookDao = new BookEJB();
}
#Test
public void createBook() throws Exception{
bookDao.createBook(newBook);
Assert.assertEquals("Book was created!", bookDao.findBookByIsbn10("0123456789"), newBook);
}
}
So when I run that test file I get following error:
Testcase: createBook(com.mysite.bookstore.tests.BookDaoTests): Caused an ERROR
null
java.lang.NullPointerException
at com.mysite.bookwebstore.beans.BookEJB.createBook(BookEJB.java:27)
at com.mysite.bookstore.tests.BookDaoTests.createBook(BookDaoTests.java:46)
EM: null
I use following technologies:
Glassfish 4
JavaEE 7
JSF
EclipseLink 2.1
Java DB
I hope we can find some solution for this problem. I have been tackling now 3 days of this problem and searched and tested solutions from Google and from Stackoverflow but none of the solutions helped/worked. To make sure that the EntityManager was really null, I debugged test file and saw that indeed it gives null. So how can I solve this problem?
The EntityManager instance, is injected when the EJB is deployed in the Container.
If you take a look at the lifecycle of enterprise bean, you will see clearly when dependency injection occurs.
When the Container sees the #Persistencecontext annotation it will inject a container-managed EntityManager.
The problem is that the code executed in this test is not managed by the Container, therefore, no one inject the necessary dependencies.
bookDao = new BookEJB();
When you run the test, the BookEJB class is just a simple POJO, the #Stateless and #PersistenceContext annotations are simply ignored.
You have several alternatives in order to test your EJB, take a look at this link.

AspectJ AOP and Spring together

I want to use AspectJ AOP and Spring (for DI) together but I get following exception:
org.springframework.beans.factory.CannotLoadBeanClassException: Cannot find class
I use IntelliJ IDEA 12 Ultimate IDE.
Here are the example steps to reproduce the error.
1: Info interface:
package org.example.bugs.bug;
public interface Info {
public void info();
}
2: Interface implementation:
package org.example.bugs.bug;
public class Informer implements Info {
#Override
public void info() {
System.out.println("Some info from Informer!");
}
}
3: Aspect:
package org.example.bugs.bug;
public aspect InfoAspect {
public InfoAspect() {}
pointcut info() : execution(* org.example.bugs.bug.Informer.info(..));
after() returning() : info() {
System.out.println("Information confirmed by InfoAspect!");
}
}
4: spring-config.xml file:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd">
<aop:aspectj-autoproxy />
<bean id="informer"
class="org.example.bugs.bug.Informer"/>
<bean class="org.example.bugs.bug.InfoAspect"
factory-method="aspectOf"/>
</beans>
5: I run everything in following Main class:
package org.example.bugs.bug;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class Main {
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("org/example/bugs/bug/spring-config.xml");
Info i = (Info) context.getBean("informer");
i.info();
}
}
...and I get error:
2013-03-24 15:46:10 org.springframework.context.support.AbstractApplicationContext prepareRefresh
INFO: Refreshing org.springframework.context.support.ClassPathXmlApplicationContext#f81843: startup date [Sun Mar 24 15:46:10 CET 2013]; root of context hierarchy
2013-03-24 15:46:10 org.springframework.beans.factory.xml.XmlBeanDefinitionReader loadBeanDefinitions
INFO: Loading XML bean definitions from class path resource [org/example/bugs/bug/spring-config.xml]
2013-03-24 15:46:10 org.springframework.beans.factory.support.DefaultListableBeanFactory preInstantiateSingletons
INFO: Pre-instantiating singletons in org.springframework.beans.factory.support.DefaultListableBeanFactory#13ad085: defining beans [org.springframework.aop.config.internalAutoProxyCreator,informer,org.example.bugs.bug.InfoAspect#0]; root of factory hierarchy
2013-03-24 15:46:10 org.springframework.beans.factory.support.DefaultSingletonBeanRegistry destroySingletons
INFO: Destroying singletons in org.springframework.beans.factory.support.DefaultListableBeanFactory#13ad085: defining beans [org.springframework.aop.config.internalAutoProxyCreator,informer,org.example.bugs.bug.InfoAspect#0]; root of factory hierarchy
Exception in thread "main" org.springframework.beans.factory.CannotLoadBeanClassException: Cannot find class [org.example.bugs.bug.InfoAspect] for bean with name 'org.example.bugs.bug.InfoAspect#0' defined in class path resource [org/example/bugs/bug/spring-config.xml]; nested exception is java.lang.ClassNotFoundException: org.example.bugs.bug.InfoAspect
at org.springframework.beans.factory.support.AbstractBeanFactory.resolveBeanClass(AbstractBeanFactory.java:1266)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.getTypeForFactoryMethod(AbstractAutowireCapableBeanFactory.java:629)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.predictBeanType(AbstractAutowireCapableBeanFactory.java:578)
at org.springframework.beans.factory.support.AbstractBeanFactory.isFactoryBean(AbstractBeanFactory.java:1335)
at org.springframework.beans.factory.support.AbstractBeanFactory.isFactoryBean(AbstractBeanFactory.java:901)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:607)
at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:932)
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:479)
at org.springframework.context.support.ClassPathXmlApplicationContext.<init>(ClassPathXmlApplicationContext.java:139)
at org.springframework.context.support.ClassPathXmlApplicationContext.<init>(ClassPathXmlApplicationContext.java:83)
at org.example.bugs.bug.Main.main(Main.java:8)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at com.intellij.rt.execution.application.AppMain.main(AppMain.java:120)
Caused by: java.lang.ClassNotFoundException: org.example.bugs.bug.InfoAspect
at java.net.URLClassLoader$1.run(URLClassLoader.java:202)
at java.security.AccessController.doPrivileged(Native Method)
at java.net.URLClassLoader.findClass(URLClassLoader.java:190)
at java.lang.ClassLoader.loadClass(ClassLoader.java:306)
at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:301)
at java.lang.ClassLoader.loadClass(ClassLoader.java:247)
at org.springframework.util.ClassUtils.forName(ClassUtils.java:260)
at org.springframework.beans.factory.support.AbstractBeanDefinition.resolveBeanClass(AbstractBeanDefinition.java:416)
at org.springframework.beans.factory.support.AbstractBeanFactory.doResolveBeanClass(AbstractBeanFactory.java:1287)
at org.springframework.beans.factory.support.AbstractBeanFactory.resolveBeanClass(AbstractBeanFactory.java:1258)
... 15 more
What I do wrong?
Because you are trying to use a pointcut supported by Spring AOP I advice you to use Spring AOP for this. Using spring with full feature set AspectJ is a little bit complicated because it requires the advice weaving. Moreover the <aop:aspectj-autoproxy /> is for #AspectJ-style spring AOP, but is still a Spring proxying the targets, not AspectJ.
So I would convert the example aspect as per below:
#Aspect
public class InfoAspect {
public InfoAspect() {
}
#Pointcut("execution(* prospring3.aop.aspectj.Informer.info(..))")
void infoPointcut() {
}
#AfterReturning("infoPointcut()")
public void afterReturning(JoinPoint joinPoint) {
System.out.println("Information confirmed by InfoAspect!");
System.out.println("joinPoint.getSignature().getName() = " + joinPoint.getSignature().getName());
}
}
#Configuration
#EnableAspectJAutoProxy(proxyTargetClass = true) // use the CGLib instead of Java Proxy
public class AspectJConfig {
#Bean
public Info info() {
return new Informer();
}
/**
* Aspect must be a config as a bean
* #return the aspect
*/
#Bean
public InfoAspect infoAspect() {
return new InfoAspect();
}
}
public class InformerTest {
public static void main(String[] args) {
ApplicationContext ctx = new AnnotationConfigApplicationContext(AspectJConfig.class);
final Info bean = ctx.getBean(Info.class);
bean.info();
}
}
Note: include the following dependencies in pom.xml
<dependency>
<groupId>aopalliance</groupId>
<artifactId>aopalliance</artifactId>
<version>1.0</version>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjrt</artifactId>
<version>1.6.12</version>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.6.12</version>
</dependency>
Regads
You're missing your InfoAspect class..
Did you not see ClassNotFound for org.example.bugs.bug.InfoAspect in the stack trace? Perhaps it's not being compiled by Aspect J.
Maybe you need another tutorial:
http://www.tutorialspoint.com/spring/aspectj_based_aop_appoach.htm
I would make sure that you've got Spring 3 and use the latest idiom.