Getting null value while unmarshalling an XML - jaxb

Can anyone please help me with this JAXB unmarshal issue?
So, this is the file employee.xml I am using:
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<parent>
<anotherchild1>Another</anotherchild1>
</parent>
and this is the Parent.java class which has JAXB annotation:
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package XMLToObject;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
/**
*
* #author Gauravb
*/
#XmlRootElement
public class Parent {
private String child;
private String anotherchild1;
public String getAnotherChild1() {
return anotherchild1;
}
public void setAnotherChild1(String child) {
this.anotherchild1 = anotherchild1;
}
}
And this is XMLToObject.java file which I am using:
package XMLToObject;
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
/**
*
* #author Gauravb
*/
import java.io.File;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Unmarshaller;
public class XMLToObject {
public static void main(String[] args) {
try {
File file = new File("employee.xml");
JAXBContext jaxbContext = JAXBContext.newInstance(Parent.class);
System.out.println("Reading....."+file.getAbsolutePath());
Unmarshaller jaxbUnmarshaller = jaxbContext.createUnmarshaller();
Parent p = (Parent) jaxbUnmarshaller.unmarshal(file);
//System.out.println("Child:"+p.getChild());
System.out.println("Another Child:"+p.getAnotherChild1());
} catch (JAXBException e) {e.printStackTrace(); }
}
}
Now, my issue is when I run XMLToObject.java file, then I see following:
Reading.....C:\xxxxxx\employee.xml
Another Child:null
So, can anyone please let me know what can be the reason behind the value as null?
Please note:
1. I am a newbie in JAXB
2. I am using Netbeans editor while running the code
3. I do NOT have XSD for the XML and dont want to use any for my learning
4. I do NOT want to use MOXy for now, this is something I will learn next

You have forgot to add #XmlElement annotation in the binding class Parent.java as below
#XmlElement
private String anotherchild1;

Related

Ignore xml element while marshalling and include xml element while unmarsalling by using XmlTransient annotation

I am trying to unmarshal an XML into an object that I expect should have a certain field. However, I do not want to marshal that object into an XML that contains it. What I like would be similar to this:
#XmlRootElement(name = "User")
public class User {
#XmlElement(namespace = "http://www.........", required = false)
private String name;
}
While marshalling , am getting below xml,
Current xml output file looks like:
<User xmlns:ns5="http://www......." />
But I don't want this namespace in output file,
Expected looks like below xml output file,
<User />
I tried to use #XmlTransient annotation,
#XmlRootElement(name = "User")
public class User {
#XmlTransient
private String name;
}
Worked successfully while marshalling and got exception while unmarshalling
org.eclipse.persistence.exceptions.XMLMarshalException
Exception Description: No descriptor found while unmarshalling element mapped to user name
Any help would be greatly appreciated.
As per my understanding, you would not want to get the namespaces in your XML. Based on my understanding providing the answer here. Hope it helps or at least guides you in the right direction.
I have done something like this:
import jakarta.xml.bind.Marshaller;
import jakarta.xml.bind.Unmarshaller;
import jakarta.xml.bind.annotation.XmlElement;
import jakarta.xml.bind.annotation.XmlRootElement;
import jakarta.xml.bind.annotation.XmlTransient;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
#Data
#NoArgsConstructor
#AllArgsConstructor
#XmlRootElement(name = "User")
public class User {
#XmlTransient
#XmlElement(namespace = "http://www.google/test.com", required = false)
private String name;
private String name1;
public void beforeMarshal(Marshaller m) {
//Executed after reading the data but before marshalling to XML. Here you can perform whatever you would like.
name1 = name;
name = null;
}
public void afterUnmarshal(Unmarshaller m, Object parent) {
//Executed after Unmarshalling the data. Here you can perform whatever you would like.
}
}
import jakarta.xml.bind.JAXBContext;
import jakarta.xml.bind.JAXBException;
import jakarta.xml.bind.Marshaller;
import javax.xml.stream.XMLStreamException;
public class Main {
public static void main(String[] args) throws JAXBException, XMLStreamException {
User user = new User();
user.setName("Batman");
final JAXBContext jaxbContext = JAXBContext.newInstance(User.class);
final Marshaller marshaller = jaxbContext.createMarshaller();
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE);
marshaller.marshal(user, System.out);
}
}
This would result in following XML:
<?xml version="1.0" encoding="UTF-8"?>
<User>
<name1>Batman</name1>
</User>
You can perform accordingly whatever you need within the beforeMarshal and afterMarshal if required.

Getting Null value on complex type element using Moxy JAXB

This is my XML which I want to unmarshal (I do not have XSD for it). And I have to unmarshal it to get an array of names and Id's. So, names are getting generated just fine, but the issue is with the Id's. The Id's are set to null. Can anyone please help me identify the issue?
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<bpmn:definitions xmlns:bpmn="http://www.omg.org/spec/BPMN/20100524/MODEL" xmlns:activiti="http://activiti.org/bpmn" xmlns:bpmndi="http://www.omg.org/spec/BPMN/20100524/DI" xmlns:dc="http://www.omg.org/spec/DD/20100524/DC" xmlns:di="http://www.omg.org/spec/DD/20100524/DI" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" expressionLanguage="http://www.w3.org/1999/XPath" id="Definitions_1" targetNamespace="http://bpmn.io/schema/bpmn" typeLanguage="http://www.w3.org/2001/XMLSchema">
<bpmn:collaboration id="Collaboration_0b6zt1k" isClosed="false">
<bpmn:participant id="Participant_113vq9r" processRef="CallActivity_00qe833" />
</bpmn:collaboration>
<bpmn:process id="CallActivity_00qe833" isClosed="false" isExecutable="true" name="Some Text" processType="None">
<bpmn:serviceTask activiti:class="Assign PC" completionQuantity="1" id="ServiceTask_0ip6tj7" implementation="##WebService" isForCompensation="false" name="Some Text 1" startQuantity="1">
<bpmn:extensionElements>
<activiti:properties>
<activiti:property name="specKey" value="ServiceTask_0ip6tj7" />
</activiti:properties>
</bpmn:extensionElements>
<bpmn:incoming>SequenceFlow_0sa9y9o</bpmn:incoming>
<bpmn:outgoing>SequenceFlow_1bd3qmp</bpmn:outgoing>
</bpmn:serviceTask>
<bpmn:serviceTask activiti:class="generateURL" completionQuantity="1" id="ServiceTask_11t11da" implementation="##WebService" isForCompensation="false" name="Some Text 2" startQuantity="1">
<bpmn:extensionElements>
<activiti:properties>
<activiti:property name="specKey" value="ServiceTask_11t11da" />
</activiti:properties>
</bpmn:extensionElements>
<bpmn:incoming>SequenceFlow_1bd3qmp</bpmn:incoming>
<bpmn:outgoing>SequenceFlow_0cynzzs</bpmn:outgoing>
</bpmn:serviceTask>
<bpmn:serviceTask activiti:class="generateURL" completionQuantity="1" id="ServiceTask_11t11da" implementation="##WebService" isForCompensation="false" name="Some Text 3" startQuantity="1">
<bpmn:extensionElements>
<activiti:properties>
<activiti:property name="specKey" value="ServiceTask_11t11da" />
</activiti:properties>
</bpmn:extensionElements>
<bpmn:incoming>SequenceFlow_1bd3qmp</bpmn:incoming>
<bpmn:outgoing>SequenceFlow_0cynzzs</bpmn:outgoing>
</bpmn:serviceTask>
</bpmn:process>
</bpmn:definitions>
This is my JAXB annotated class:
package XMLToObject;
import java.util.List;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.XmlRootElement;
import org.eclipse.persistence.oxm.annotations.XmlPath;
#XmlRootElement
#XmlAccessorType(XmlAccessType.FIELD)
public class definitions {
#XmlPath("bpmn:process/bpmn:serviceTask/#name")
#XmlAttribute
List<String> name;
#XmlPath("bpmn:process/bpmn:serviceTask/#id")
#XmlAttribute
List<String> id;
#XmlAttribute
String typeLanguage;
public List<String> getname() {
return name;
}
public List<String> getid() {
return id;
}
public String gettypeLanguage() {
return typeLanguage;
}
}
This is my Java Class:
package XMLToObject;
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
/**
*
* #author Gauravb
*/
import java.io.File;
import java.util.Collection;
import java.util.List;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Unmarshaller;
public class XMLToObject {
public static void main(String[] args) {
try {
File file = new File("employee.xml");
JAXBContext jaxbContext = JAXBContext.newInstance(definitions.class);
System.out.println("JAXB....."+jaxbContext.toString());
Unmarshaller jaxbUnmarshaller = jaxbContext.createUnmarshaller();
definitions p = (definitions) jaxbUnmarshaller.unmarshal(file);
System.out.println("Task Name:"+p.getname());
System.out.println("Svc ID:"+p.getid());
System.out.println("Type Language:"+p.gettypeLanguage());
} catch (JAXBException e) {e.printStackTrace(); }
}
}
Now, this is the output I am getting:
run:
JAXB.....org.eclipse.persistence.jaxb.JAXBContext#18eed359
Task Name:[Some Text 1, Some Text 2, Some Text 3]
Svc ID:null
Type Language:http://www.w3.org/2001/XMLSchema
BUILD SUCCESSFUL (total time: 0 seconds)
My issue is that why I am getting Svc ID as "null" when the same is working for Task Name.
Please note:
1. I am using MOXy for JAXB
2. Please note that when I change the sequence then names are getting set to null:
#XmlPath("bpmn:process/bpmn:serviceTask/#id")
#XmlAttribute
List<String> id;
#XmlPath("bpmn:process/bpmn:serviceTask/#name")
#XmlAttribute
List<String> name;
I am getting this output:
run:
JAXB.....org.eclipse.persistence.jaxb.JAXBContext#18eed359
Task Name:null
Svc ID:[ServiceTask_0ip6tj7, ServiceTask_11t11da, ServiceTask_11t11da]
Type Language:http://www.w3.org/2001/XMLSchema
BUILD SUCCESSFUL (total time: 0 seconds)
Looks like mulltiple attributes on Moxy is not supported (What a shame :( I just started to love MOXy)
Attached is a link
With MOXy and XPath, is it possible to unmarshal two lists of attributes?

How to remove the element name from xml?

I am trying to create a person rest service.And am trying to create xml schema using JAXB and JSon Schema Using Jackson.
So Here is my Model classes to create the respective XML as well as JSon Payload.
package www.tempuri.person.model;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import javax.xml.bind.annotation.XmlRootElement;
import com.fasterxml.jackson.annotation.JsonRootName;
#ApiModel(value="GetPerson Message",description = "Personal Input Request")
#XmlRootElement(name="getPerson")
#JsonRootName(value = "getPerson")
public class GetPersonWrapper {
#ApiModelProperty(value = "GetPerson", required = true)
private GetPerson getPerson;
public GetPerson getGetPerson() {
return getPerson;
}
public void setGetPerson(GetPerson getPerson) {
this.getPerson = getPerson;
}
}
package www.tempuri.person.model;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
#ApiModel(description = "Represents Persons")
public class GetPerson {
#ApiModelProperty(value = "Application Area of GetPerson", required = true)
private ApplicationArea applicationArea;
#ApiModelProperty(value = "Data Area of GetPerson", required = true)
private DataAreaGet dataArea;
/**
* #return the dataArea
*/
public DataAreaGet getDataArea() {
return dataArea;
}
/**
* #param dataArea the dataArea to set
*/
public void setDataArea(DataAreaGet dataArea) {
this.dataArea = dataArea;
}
public ApplicationArea getApplicationArea() {
return applicationArea;
}
public void setApplicationArea(ApplicationArea applicationArea) {
this.applicationArea = applicationArea;
}
}
With the above model classes, the json schema is coming as intended. But in case of xml i am not able to get what i want to:
Below is the schema that it generated in xml:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<getPerson>
<getPerson>
<applicationArea/>
<dataArea>
<description>string</description>
<id>0</id>
<name>string</name>
</dataArea>
</getPerson>
</getPerson>
As you can see i am getting two getPerson Node. How can i remove one of the getPerson node using the jaxb annotations only.
I am using apache camel swagger component to create the rest service.
Looking forward to your solutions. Thanks in advance.
I would use XSLT, straight forward , simple and works like a magic.

How to use of XmlGregorianCalendar with fromJson and toJson methods of gson?

The theme of my project is to give XML format of data and get Json format using google-gson and I have JAXB generated java POJOs from XML schema in which I have a variable of XMLGregorianCalendar datatype.
I give the following input of XML and get the json format from the gson.toJson() method;
<?xml version="1.0" encoding="UTF-8"?>
<EmpRequest xmlns="http://java.com/Employee">
<EmplIn>
<EmpID>12</EmpID>
<Empname>sara</Empname>
<Designation>SA</Designation>
<DOJ>2002-05-30T09:30:10+06:00</DOJ>
</EmplIn>
</EmpRequest>
But in the output, I got the following.
{"emplIn":{"empID":"12","empname":"sara","designation":"SA","doj":{}}}
I surfed google and got the suggestion of adding in the xml schema and changing the XmlGregorianCalendar datatype with string. But I dont want to achieve it from both the ways.
I mean how to get the proper output with the XmlGregorianCalendar datatype through fromJson and toJson methods of gson?
Thank you so much,
Harish Raj.
Hopefully, This can fix my issue of using google-gson.
(The following should be added in where we create the object of Gson)
Step 1:
Gson gson =
new GsonBuilder().registerTypeAdapter(XMLGregorianCalendar.class,
new XGCalConverter.Serializer()).registerTypeAdapter(XMLGregorianCalendar.class,
new XGCalConverter.Deserializer()).create();
Step 2: And we need to create the XGCalConverter Class as like the following.
import com.google.gson.JsonDeserializationContext;
import com.google.gson.JsonDeserializer;
import com.google.gson.JsonElement;
import com.google.gson.JsonPrimitive;
import com.google.gson.JsonSerializationContext;
import com.google.gson.JsonSerializer;
import java.lang.reflect.Type;
import javax.xml.datatype.DatatypeFactory;
import javax.xml.datatype.XMLGregorianCalendar;
public class XGCalConverter
{
public static class Serializer implements JsonSerializer
{
public Serializer()
{
super();
}
public JsonElement serialize(Object t, Type type,
JsonSerializationContext jsonSerializationContext)
{
XMLGregorianCalendar xgcal=(XMLGregorianCalendar)t;
return new JsonPrimitive(xgcal.toXMLFormat());
}
}
public static class Deserializer implements JsonDeserializer
{
public Object deserialize(JsonElement jsonElement, Type type,
JsonDeserializationContext jsonDeserializationContext)
{
try
{
return DatatypeFactory.newInstance().newXMLGregorianCalendar(jsonElement.getAsString());
}
catch(Exception ex)
{
ex.printStackTrace();
return null;
}
}
}
}
Note: I'm the EclipseLink JAXB (MOXy) lead and a member of the JAXB 2 (JSR-222) expert group.
You could use MOXy to handle both the XML and JSON binding aspects of this use case. As I mentioned in my comment MOXy supports the XMLGregorianCalendar type. The Metadata would look like:
EmpRequest
package forum7725188;
import javax.xml.bind.annotation.*;
#XmlRootElement(name="EmpRequest")
#XmlAccessorType(XmlAccessType.FIELD)
public class EmpRequest {
#XmlElement(name="EmplIn")
private EmplIn emplIn;
}
EmplIn
package forum7725188;
import javax.xml.bind.annotation.*;
import javax.xml.datatype.XMLGregorianCalendar;
#XmlAccessorType(XmlAccessType.FIELD)
public class EmplIn {
#XmlElement(name="EmpID")
private long empId;
#XmlElement(name="Empname")
private String name;
#XmlElement(name="Designation")
private String designation;
#XmlElement(name="DOJ")
private XMLGregorianCalendar doj;
}
package-info
#XmlSchema(namespace="http://java.com/Employee", elementFormDefault=XmlNsForm.QUALIFIED)
#XmlAccessorType(XmlAccessType.FIELD)
package forum7725188;
import javax.xml.bind.annotation.*;
Demo
You can configure the MOXy implementation of Marshaller to output JSON by setting the eclipselink.media-type property to be application/json.
package forum7725188;
import java.io.File;
import javax.xml.bind.*;
import javax.xml.namespace.QName;
public class Demo {
public static void main(String[] args) throws Exception {
JAXBContext jc = JAXBContext.newInstance(EmpRequest.class);
Unmarshaller unmarshaller = jc.createUnmarshaller();
File xml = new File("src/forum7725188/input.xml");
EmpRequest empRequest = (EmpRequest) unmarshaller.unmarshal(xml);
JAXBElement<EmpRequest> jaxbElement = new JAXBElement<EmpRequest>(new QName(""), EmpRequest.class, empRequest);
Marshaller marshaller = jc.createMarshaller();
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
marshaller.setProperty("eclipselink.media-type", "application/json");
marshaller.marshal(jaxbElement, System.out);
}
}
input.xml
<?xml version="1.0" encoding="UTF-8"?>
<EmpRequest xmlns="http://java.com/Employee">
<EmplIn>
<EmpID>12</EmpID>
<Empname>sara</Empname>
<Designation>SA</Designation>
<DOJ>2002-05-30T09:30:10+06:00</DOJ>
</EmplIn>
</EmpRequest>
Output
{"EmplIn" :
{"EmpID" : "12",
"Empname" : "sara",
"Designation" : "SA",
"DOJ" : "2002-05-30T09:30:10+06:00"}}
For More Information
http://blog.bdoughan.com/2011/08/binding-to-json-xml-geocode-example.html
http://blog.bdoughan.com/2011/08/json-binding-with-eclipselink-moxy.html
http://blog.bdoughan.com/2011/05/specifying-eclipselink-moxy-as-your.html
http://blog.bdoughan.com/2011/09/mapping-objects-to-multiple-xml-schemas.html

Is it possible to override facelets.development for different environments?

We'd like to set facelets.development to false to suppress stack traces in non-development environments, but we'd like to have it set to true in dev for debugging.
Our deployment process dictates one CI build that is migrated through the environments up to production, so we can't use an approach that requires rebuilding the app / rewriting web.xml for each environment. We'd like to change the value from the application, based on a properties file setting. Is this possible? How can the application access facelets.development?
I think the simplest approach is to put the Context parameter in web.xml:
<context-param>
<param-name>facelets.DEVELOPMENT</param-name>
<param-value>false</param-value>
</context-param>
and override it in your Development deployments. This is usually possible without changing the WAR. In Tomcat, include META-INF/context.xml in your WAR with this line (within <Context> ... </Context>):
<Parameter name="facelets.DEVELOPMENT" value="true" override="false" />
Tomcat will copy this file on startup to $CATALINA_BASE/conf/[enginename]/[hostname]/[context-path-name].xml which can be used to configure the webapp outside the
WAR. This will happen in each of your environments and admins have to change it only once to:
<Parameter name="facelets.DEVELOPMENT" value="false" override="false" />
Afterwards, Tomcat will not overwrite it even if a new WAR with a newer /META-INF/context.xml is deployed. The names of context Parameters have to match the declarations in WEB-INF/web.xml.
See http://tomcat.apache.org/tomcat-6.0-doc/config/context.html for details ("Introduction" and "Context Parameters" section).
I can think of a few ways to do this, none of them very pleasant.
Decorate the FacesContext to control the init parameters programmatically. This is a lot of work for so little gain.
Patch the FaceletViewHandler class to get the behaviour you want. This may add maintenance overhead if you upgrade your Facelets libs. May make the folks who manage the app in production unhappy.
A variation on the patch approach is to just use the patched JARs in your dev/test machines and put them in the server libs - then use PARENT_FIRST classloading to load them over JARs in the apps (assuming your app server supports all that). The downside of this is that it imposes classloading policies and you have to manage JARs all over the place.
I would favour some other approach. If this setting is required on test machines, perhaps a deployment script could modify the app during the install for those servers. If you want it set to true in your source control, the build script could remove it as part of the build process. This approach would have no impact on your runtime code.
I've implemented a variation on option 1 above. eg
wrote a dynamic proxy for a ServletContext that intercepts the getInitParameter and getInitParameterNames methods returning appropriate values (sourced from environment-specific property files in this case)
wrote a very small subclass of FacesContextFactoryImpl that proxies the first/servletcontext parameter to getFacesContext and then delegates to the superclass.
added a faces-context-factory clause to my faces-config naming my FacesContextFactoryImpl class
I already had a mechanism in place to load environment-specific property files and make them available as a Properties object to the application (the factory in point 2 passes these properties to the proxy in point 1 to use as an alternate source of initParameter values)
The proxy looks like:
package zzzzz.framework.context;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.Enumeration;
import java.util.Hashtable;
import java.util.Map;
import javax.servlet.ServletContext;
import org.apache.commons.collections.IteratorUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
/**
* A proxy for ServletContext that intercepts accesses to the initParameters and
* returns values from the specified params instead. Generally useful if we have
* a set of properties (eg SystemContext.getInstance().getConfigProperties()) that
* we want to use in preference to the webapp initProperties.
*
*
*/
public class ServletContextProxy
implements InvocationHandler {
#SuppressWarnings("unused")
private static final Log log = LogFactory.getLog(ServletContextProxy.class);
#SuppressWarnings("unchecked")
public static ServletContext newInstance(ServletContext subject,
Map params) {
return newInstance(subject,
params,
true);
}
#SuppressWarnings("unchecked")
public static ServletContext newInstance(ServletContext subject,
Map params,
boolean overrideInitValues) {
return (ServletContext) Proxy.newProxyInstance(subject.getClass()
.getClassLoader(),
subject.getClass()
.getInterfaces(),
new ServletContextProxy(subject,
params,
overrideInitValues));
}
/**
* A convenience method to help extracting the initParameters from a
* ServletContext because it doesn't expose it's underlying Map
*
* #param config
* #return
*/
#SuppressWarnings("unchecked")
protected static Map copyInitParameters(Map parms,
ServletContext config) {
Enumeration names = config.getInitParameterNames();
// copy all the existing initParameters
while (names.hasMoreElements()) {
String name = (String) names.nextElement();
parms.put(name,
config.getInitParameter(name));
}
return parms;
}
private boolean overrideInitValues = true;
#SuppressWarnings("unchecked")
private Map params;
private ServletContext subject;
#SuppressWarnings("unchecked")
public ServletContextProxy(ServletContext subject,
Map params,
boolean overrideInitValues) {
this.subject = subject;
this.overrideInitValues = overrideInitValues;
this.params = new Hashtable();
if (this.overrideInitValues) { // default behaviour... supplied parameters win
// start with initParameters
copyInitParameters(this.params,
subject);
// override and supplement with supplied params
if (params != null) {
this.params.putAll(params);
}
} else {
// start with supplied params
if (params != null) {
this.params.putAll(params);
}
// override and supplement with initParameters
copyInitParameters(this.params,
subject);
}
}
public Object invoke(Object proxy,
Method m,
Object[] args) throws Throwable {
Object result;
try {
if ("getInitParameter".equals(m.getName())) {
result = this.params.get(args[0]);
} else if ("getInitParameterNames".equals(m.getName())) {
result = IteratorUtils.asEnumeration(this.params.keySet()
.iterator());
} else {// else let it go through to the keeper
result = m.invoke(this.subject,
args);
}
} catch (InvocationTargetException e) {
throw e.getTargetException();
} catch (Exception e) {
throw new RuntimeException("unexpected invocation exception: "
+ e.getMessage());
}
return result;
}
}
The factory looks like:
package zzz.faces.context;
import javax.faces.FacesException;
import javax.faces.context.FacesContext;
import javax.faces.lifecycle.Lifecycle;
import javax.servlet.ServletContext;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import zzzzz.framework.context.ServletContextProxy;
import zzzzz.context.SystemContext;
/**
* A FacesContextFactory implementation that supplements/overrided the
* servletContext initParemeters with properties form
* SystemContext.configProperties
* <p>
* The point of this is that it allows us to substitute configuration in the
* web.xml like this (which requires rewriting web.xml to change)
* </p>
*
* <pre>
* <!-- Enables special Facelets debug output during development -->
* <context-param>
* <param-name>facelets.DEVELOPMENT</param-name>
* <param-value>true</param-value>
* </context-param>
* </pre>
*
* <p>
* with settings in the relevent application.properties file like this (which
* can be changed separately to the webapp)
* </p>
*
* <pre>
* # Enables special Facelets debug output during development
* facelets.DEVELOPMENT=true
* </pre>
*
* <p>
* usage: add a clause to faces-config like this:
*
* <pre>
* <factory>
* <faces-context-factory>zzzzz.faces.context.FacesContextFactoryImpl</faces-context-factory>
* </factory>
* </pre>
* <p>
*
*/
public class FacesContextFactoryImpl extends com.sun.faces.context.FacesContextFactoryImpl {
#SuppressWarnings("unused")
private static final Log log = LogFactory.getLog(FacesContextFactoryImpl.class);
public FacesContextFactoryImpl() {
super();
}
#Override
public FacesContext getFacesContext(Object sc,
Object request,
Object response,
Lifecycle lifecycle) throws FacesException {
if (sc instanceof ServletContext
&& !(sc instanceof ServletContextProxy)) {
// wrap the servlet context with a proxy to override/supplement initParameters
sc = ServletContextProxy.newInstance((ServletContext) sc,
SystemContext.getInstance()
.getConfigProperties(),
true);
}
return super.getFacesContext(sc,
request,
response,
lifecycle);
}
}
and the faces-config looks like
<faces-config>
blah waffle....
<factory>
<faces-context-factory>zzzz.faces.context.FacesContextFactoryImpl</faces-context-factory>
</factory>
</faces-config>
What SystemContext.getInstance().getConfigProperties() looks like is an excercise for another day but it just returns the Map of property values the app is supposed to use

Resources