WildFly does not run my LiquibaseProcucer CDI - cdi

I'm trying to run my LiquibaseProducer in WildFly 9.0.2. This is my Producer class:
package nl.itris.mjop.database;
import liquibase.integration.cdi.*;
import liquibase.integration.cdi.annotations.*;
import liquibase.resource.*;
import **********
#Singleton
#Startup
#Dependent
public class LiquibaseProcducer {
#Resource(lookup="java:jboss/datasources/PostgresDS")
private static DataSource myDataSource;
#Produces #LiquibaseType
public CDILiquibaseConfig createConfig() {
System.out.println("============= liquibase createConfig entry =============");
CDILiquibaseConfig config = new CDILiquibaseConfig();
config.setChangeLog("liquibase/parser/core/xml/simpleChangeLog.xml");
System.out.println("============= liquibase createConfig exit =============");
return config;
}
#Produces #LiquibaseType
public DataSource createDataSource() throws SQLException {
System.out.println("============= liquibase createDataSource entry =============");
return getDataSource();
}
#Produces #LiquibaseType
public ResourceAccessor create() {
System.out.println("============= liquibase create entry =============");
return new ClassLoaderResourceAccessor(getClass().getClassLoader());
}
public static DataSource getDataSource() {
if (myDataSource == null) {
/* Workaround for failing #Resource(lookup="java:jboss/datasources/PostgresDS") */
try {
System.out.println("============= liquibase datasource lookup via initial context workaround =============");
InitialContext ctx = new InitialContext();
myDataSource = (DataSource) ctx.lookup("java:jboss/datasources/PostgresDS");
} catch(NamingException ne) {
ne.printStackTrace();
}
}
return myDataSource;
}
}
When I (re) deploy my WAR file in WildFly, this producer is not doing anything! I do not see any error messages in my log files, I do not see any system.out messages that I put in the producer methods.
The producer class seems to be loaded and recognized by WildFly hence this log fragment:
2016-11-30 10:58:53,662 INFO [org.jboss.as.ejb3.deployment.processors.EjbJndiBindingsDeploymentUnitProcessor] (MSC service thread 1-7) JNDI bindings for session bean named LiquibaseProcducer in deployment unit deployment "mjop-elements.war" are as follows:
java:global/mjop-elements/LiquibaseProcducer!nl.itris.mjop.database.LiquibaseProcducer
java:app/mjop-elements/LiquibaseProcducer!nl.itris.mjop.database.LiquibaseProcducer
java:module/LiquibaseProcducer!nl.itris.mjop.database.LiquibaseProcducer
java:global/mjop-elements/LiquibaseProcducer
java:app/mjop-elements/LiquibaseProcducer
java:module/LiquibaseProcducer
I'm out of options. Why is my producer not executed? What am I doing wrong?
Any help is appreciated!
My beans.xml is like this:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee
http://xmlns.jcp.org/xml/ns/javaee/beans_1_1.xsd"
version="1.1" bean-discovery-mode="all">
</beans>

Related

CDI cross BDA bean injection in Wildfly 8.1

I have an EAR file with the following structure:
lib
jar.jar
Test1
Test2
ejb.jar
Test1Impl
war.war
Test2Impl
TestServlet
The jar.jar contains two interfaces
Test1
Test2
The TestServlet injects Test1 which resolves to Test1Impl only if I have a manifest Class-Path entry in war.war to ejb.jar.
Test1Impl injects Test2 which resolves to Test2Impl only if I have a manifest Class-Path entry in ejb.jar to war.war.
The tip entry Matching the classloader structure for the deployment of the Weld documentation explains why I need the manifest entries.
How is this cross BDA injection supposed to work normally? Adding Class-Path manifest entries seems a bit stupid because actually I don't want the implementations to be visible. I only want that the beans from other subdeployments to be visible. Is there any way to do that?
Here the implementations
public class Test1Impl implements Test1 {
#Inject
private Test2 test2;
public void hello() {
System.out.println(test2.getString());
}
}
public class Test2Impl implements Test2 {
public String getString() {
return "Hello";
}
}
#WebServlet(urlPatterns = "/test")
public class TestServlet implements Servlet {
#Inject
private Test1 test;
public void init(ServletConfig config) throws ServletException {
}
public ServletConfig getServletConfig() {
return null;
}
public void service(ServletRequest req, ServletResponse res) throws ServletException, IOException {
test.hello();
}
public String getServletInfo() {
return null;
}
public void destroy() {
}
}
And here the application.xml
<?xml version="1.0" encoding="UTF-8"?>
<application xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/application_7.xsd"
version="7">
<description>The EAR</description>
<display-name>ear</display-name>
<module>
<ejb>ejb.jar</ejb>
</module>
<module>
<web>
<web-uri>war.war</web-uri>
<context-root>/</context-root>
</web>
</module>
<library-directory>lib</library-directory>
</application>
As described in the CDI reference in the section Using CDI Beans from outside the deployment a jboss-deployment-structure.xml with the appropriate dependencies is required.
Although doing this fixed my problems, I think that the CDI spec should define a portable way for doing this for enterprise applications.

How to log specific exception if i am already using FullAjaxExceptionHandler

I am using FullAjaxExceptionHandler to handle timeout issue in ajax request. The problem that I am facing is to handle javax.faces.view.facelets.FaceletException. If i have an error in the xhtml page, i dont want to show the stack trace instead show an error page. This i have achieved by specifying error page in web.xml. The problem is that i want to log this error. I am using log4j for other exceptions, but how to write handler for FaceletException. If write another Exception handler is there an order in which i should specify the handler class because i am already using FullAjaxExceptionHandler.
faces-config.xml:
<application>
<el-resolver>
org.springframework.web.jsf.el.SpringBeanFacesELResolver
</el-resolver>
</application>
<factory>
<exception-handler-factory>org.omnifaces.exceptionhandler.FullAjaxExceptionHandlerFactory</exception-handler-factory>
</factory>
<render-kit>
<renderer>
<component-family>org.primefaces</component-family>
<renderer-type>org.primefaces.component.ScheduleRenderer</renderer-type>
<renderer-class>com.example.domain.web.custom.MyScheduleRenderrer</renderer-class>
</renderer>
</render-kit>
Add a custom Exception handler factory in faces-config.xml
<application>
<el-resolver>
org.springframework.web.jsf.el.SpringBeanFacesELResolver
</el-resolver>
</application>
<factory>
<exception-handler-factory>com.fetchinglife.domain.web.permissions.CustomExceptionHandlerFactory</exception-handler-factory>
</factory>
Create custom exception handler factory
public class CustomExceptionHandlerFactory extends ExceptionHandlerFactory{
private ExceptionHandlerFactory wrapped;
public CustomExceptionHandlerFactory(ExceptionHandlerFactory wrapped) {
this.wrapped = wrapped;
}
#Override
public ExceptionHandler getExceptionHandler() {
return new CustomExceptionHandler(wrapped.getExceptionHandler());
}
#Override
public ExceptionHandlerFactory getWrapped() {
return wrapped;
}
}
Create custom exception handler
public class CustomExceptionHandler extends FullAjaxExceptionHandler{
static Logger log = Logger
.getLogger(CustomExceptionHandler.class);
public CustomExceptionHandler(ExceptionHandler wrapped) {
super(wrapped);
}
#Override
public void handle() throws FacesException {
Iterator<ExceptionQueuedEvent> unhandledExceptionQueuedEvents = getUnhandledExceptionQueuedEvents().iterator();
if(unhandledExceptionQueuedEvents.hasNext()){
Throwable exception = unhandledExceptionQueuedEvents.next().getContext().getException();
log.error("FL Error",exception);
}
super.handle();
}
}
Unfortunately, it appears that you can't have both.
From The JSF Spec, the ExceptionHandlerFactory is expecting a single type to be configured
From the source of the FullAjaxExceptionHandler, if the exception is non-ajax, it's rethrown, to be handled by the <error-page> mechanism.
You'll either have to extend or wrap the FullAjaxExceptionHandler to provide both Ajax and Non-Ajax exception handling

Jersey Restful Web Service - MessageBodyProviderNotFoundException

I'm new to Java Web Services and I'm struggling with a basic problem.
After finding a bunch of outdated examples I managed to get something working with XML however the same code wont work when I ask it to return JSON.
Initially I thought it was a missing JSON formatter but JAXB should be taking care of the conversion from POJO to JSON so I don't believe that's the problem.
The error being thrown within Tomcat is:
javax.servlet.ServletException: org.glassfish.jersey.message.internal.MessageBodyProviderNotFoundException: MessageBodyWriter not found for media type=application/json, type=class resttest.model.Todo, genericType=class resttest.model.Todo
WEB.XML
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
id="WebApp_ID" version="2.5">
<display-name>testtest</display-name>
<servlet>
<servlet-name>Jersey REST Service</servlet-name>
<servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class>
<init-param>
<param-name>jersey.config.server.provider.packages</param-name>
<param-value>resttest.jaxb;resttest.model</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>Jersey REST Service</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping>
</web-app>
Todo.java
package resttest.model;
import javax.xml.bind.annotation.XmlRootElement;
#XmlRootElement
public class Todo {
public Todo(){};
private String summary;
private String description;
public String getSummary() {
return summary;
}
public void setSummary(String summary) {
this.summary = summary;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
}
TodoResource.Java
package resttest.jaxb;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import resttest.model.Todo;
#Path("/todo")
public class TodoResource {
#GET
#Produces("application/json")
public Todo getTodo() {
Todo todo = new Todo();
todo.setSummary("This is my first todo");
todo.setDescription("This is my first todo");
return todo;
}
}
Any ideas why the JSON isn't being returned and the error thrown?
I searched a lot of the responses myself and this is what I ended up doing. In addition to your TodoResource class, you need a class that extends Application, and class such as the MOXyJsonContextResolver class below to implement the ContextResolver interface. These help define the Jersey context along with a selected Json converter and optional customizations to the Json output. Put the classes in the same package as your resource class and Jersey will find it. MOXy is now the default for Jersey (I use 2.5.1) and the only json converter that I could get working without receiving your error. Also, make sure you have the MOXy jar included in your build or maven pom.xml (jersey-media-moxy-2.5.1.jar).
Note: nothing is in my application's web.xml. That was in the older documentation examples and not needed as of Jersey 2.5.1.
#javax.ws.rs.ApplicationPath("webresources")
public class ApplicationConfig extends Application {
public ApplicationConfig() {
this.initMethods();
}
#Override
public Set<Class<?>> getClasses() {
Set<Class<?>> resources = new java.util.HashSet<Class<?>>();
addRestResourceClasses(resources);
return resources;
}
private void initMethods() {
try {
...some classes you might need instantiated, etc, for your resource class
} catch (Exception e) {
e.printStackTrace();
}
}
private void addRestResourceClasses(Set<Class<?>> resources) {
resources.add(MOXyJsonContextResolver.class);
}
}
And here is the MOXyJsonContextResolver.class that I used to customize the Json response:
public class MOXyJsonContextResolver implements ContextResolver<MoxyJsonConfig> {
private final MoxyJsonConfig config;
public MOXyJsonContextResolver() {
config = new MoxyJsonConfig()
.setAttributePrefix("")
.setValueWrapper("value")
.property(JAXBContextProperties.JSON_WRAPPER_AS_ARRAY_NAME, true);
}
#Override
public MoxyJsonConfig getContext(Class<?> objectType) {
return config;
}
}
You forgot to add the attribute: #XmlAccessorType(XmlAccessType.FIELD)
Example:
#XmlRootElement
#XmlAccessorType(XmlAccessType.FIELD)
public class Todo {
...
You have mentioned #XmlRootElement at class level in todo class. #XmlRootElement is only required if you want to produce your response in xml format, and also provide #Path at method level in TodoResource class, its a good practice.
mention #Produces(MediaType.APPLICATION_JSON) at method level. Hope this will work for you!

How to save theme in Primefaces

I want to use Primefaces ThemeSwitcher. I'm interested how I can save the selected theme when I reload the web application. For example how I can set the theme name as variable from database?
You won't be needing the ThemeSwitcher to effect the kind of persistence you're looking for.
Simply perform the database lookup for the theme in a ServletContextListener and then store the value in the servlet context, possibly overriding whatever you've set in the web.xml
public Class MyContextListener implements ServletContextListener{
public void contextInitialized(ServletContextEvent sce){
String selectedTheme = myThemeDAO.getConfiguredTheme();
sce.getServletContext().setInitParameter("primefaces.THEME",selectedTheme);
}
}
link your ThemeSwitcher component to a managedBean and add a listener linked to a ajax event:
<h:form id="form-theme">
<p:themeSwitcher id="defaultSwitcher" value="#{themeSwitcherBean.theme}">
<f:selectItems value="#{themeSwitcherBean.themes}" />
<p:ajax listener="#{themeSwitcherBean.saveTheme}" />
</p:themeSwitcher>
</h:form>
in your managedbean create the method who call saveTheme, that going to call a class to persist in database, and call the the class for the database when start to get the theme who had saved into the database:
#SessionScoped
#ManagedBean(name="themeSwitcherBean")
public class ThemeSwitcherBean implements Serializable{
private Map<String, String> themes;
private String theme;
private GuestPreferences gp;
private void setGp(GuestPreferences gp) {
this.gp = gp;
}
public Map<String, String> getThemes() {
return themes;
}
public String getTheme() {
return theme;
}
public void setTheme(String theme) {
this.theme = theme;
}
#PostConstruct
public void init() {
setGp(new GuestPreferences()); // persistent class
setTheme(gp.getTheme()); // theme from the database;
themes = new TreeMap<String, String>();
themes.put("Aristo", "aristo");
themes.put("Black-Tie", "black-tie");
themes.put("Blitzer", "blitzer");
themes.put("Bluesky", "bluesky");
themes.put("Bootstrap", "bootstrap");
themes.put("Casablanca", "casablanca");
themes.put("Cupertino", "cupertino");
themes.put("Dark-Hive", "dark-hive");
themes.put("Dot-Luv", "dot-luv");
themes.put("Eggplant", "eggplant");
themes.put("Excite-Bike", "excite-bike");
themes.put("Flick", "flick");
themes.put("Glass-X", "glass-x");
themes.put("Hot-Sneaks", "hot-sneaks");
themes.put("Humanity", "humanity");
themes.put("Le-Frog", "le-frog");
themes.put("Midnight", "midnight");
themes.put("Mint-Choc", "mint-choc");
themes.put("Overcast", "overcast");
themes.put("Pepper-Grinder", "pepper-grinder");
themes.put("Redmond", "redmond");
themes.put("Rocket", "rocket");
themes.put("Sam", "sam");
themes.put("Smoothness", "smoothness");
themes.put("South-Street", "south-street");
themes.put("Start", "start");
themes.put("Sunny", "sunny");
themes.put("Swanky-Purse", "swanky-purse");
themes.put("Trontastic", "trontastic");
themes.put("UI-Darkness", "ui-darkness");
themes.put("UI-Lightness", "ui-lightness");
themes.put("Vader", "vader");
}
public void saveTheme() {
gp.setTheme(theme); // theme to database
}
}
method theme from class GuestPreferences is going to persist to the database
#SessionScoped
public class GuestPreferences {
public String getTheme(){
//return the theme from the database
}
public void setTheme(String theme){
//send the theme to the database
}
}
the form to send and receive data from the database depends of you prefer:
* jdbc
* jta
* jpa
for example, jta, make a persistence.xml:
<?xml version="1.0" encoding="UTF-8"?>
<persistence version="2.0" xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation=" http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd">
<persistence-unit name="NAME-WHAT-YOU-WANT" transaction-type="JTA">
<provider>CLASS-OF-YOUR-PROVIDER</provider>
<jta-data-source>YOUR-DATASOURCE</jta-data-source>
<class>PATH-OF.GuestPreferences</class>
<properties>
<property name="NAME-OF-PROPERTY-TO-FORM-A-JDBC-URL" value="VALUE-OF-PROPERTY"/>
<property name="NAME-OF-PROPERTY-TO-FORM-A-JDBC-URL" value="VALUE-OF-PROPERTY"/>
<property name="NAME-OF-PROPERTY-TO-FORM-A-JDBC-URL" value="VALUE-OF-PROPERTY"/>
</properties>
</persistence-unit>
</persistence>
in a resources class you can declare:
#SuppressWarnings("unused")
#Produces
#PersistenceContext
private EntityManager em;
then, you can use it in your GuestPreferences class:
#Inject
private EntityManager em;
em.getTransaction().begin();
Query query = em.createQuery("SELECT u FROM user_table u where u.iduser=:iduser");
query.setParameter("iduser", "THEME-USER-ID");
User resultUser = (User) query.getResultList();
em.getTransaction().commit();
if(User!=null){
return resultUser.getTheme();
}
code above assumes you have a table called user_table where a user has a iduser, name ..., and a theme column, and it assumes you have an object called User to manage users
One more way to do this: include stylesheet to your pages template:
<h:body>
<h:outputStylesheet library="primefaces-#{themesBean.theme}" name="theme.css" /> </h:body>
Where #{themesBean.theme} variable reffers to name of your theme.
P.S. tested in PF5
I think setting selected theme in session would help:
session.setAttribute
Edit web.xml through code:
http://illegalargumentexception.blogspot.co.at/2008/08/java-using-xmlbeans-to-edit-webxml.html
<context-param>
<param-name>primefaces.THEME</param-name>
<param-value>EDITME</param-value>
</context-param>
Or create method before loading your page to choose the theme from db. (cleaner solution)

JSF receiving FacesContext outside request

As far as i know, FacesContext is avalible only in request scope. I've created a thread that tries to receive instance of FacesContext, but it is returning null.
My point is to update some application-scoped beans every 10 seconds.
Thread's run method:
#Override
public void run()
{
while (true)
{
try
{
TimeView timeView = (TimeView)FacesContext.getCurrentInstance().
getExternalContext().getApplicationMap().get("timeView");
// FacesContext.getCurrentInstalce() returns null
timeView.update();
Thread.sleep(10000);
}
catch (InterruptedException ex)
{
System.out.println(ex);
}
}
}
TimeView's header (I've skipped getters/setters):
#ManagedBean(eager=true, name="timeView")
#ApplicationScoped
public class TimeView implements Serializable
{
private int hour;
private int minutes;
private int seconds;
public TimeView()
{
update();
}
public void update()
{
Date date = new Date();
setHour(date.getHours());
setMinutes(date.getMinutes());
setSeconds(date.getSeconds());
}
faces-config.xml:
<?xml version="1.0" encoding="UTF-8"?>
<faces-config
xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/web-facesconfig_2_0.xsd"
version="2.0">
<managed-bean>
<managed-bean-name>timeView</managed-bean-name>
<managed-bean-class>foogame.viewBeans.TimeView</managed-bean-class>
<managed-bean-scope>application</managed-bean-scope>
</managed-bean>
</faces-config>
So, is there a way to receive refference to my application-scoped beans in this thread?
As there is now way to access/construct FacesContext outside of Servlet environment, I recommend you to pass the application scoped object to the constructor of the worker thread (the thread that performs the batch job). Updating the reference in the thread will result in updating the application scoped reference because they both point to the same instance.
If you have an EJB3 environment you could use EJB timer + #Singleton bean without the need to deal with threads and scopes.

Resources