I need to use function with argument in a EL expression (with JSF) like this:
<h:outputText value="#{object.test(10)}" ></h:outputText>
But it doesn't work.
I read on the web that it's impossible to do this with JSF. I use facelet with JSF.
Someone knows how to do that ?
Thanks.
You could provide the method as a custom facelet function in your own taglib. The method must be static, so if you are trying to call a method on a specific bean, you would have to pass the bean, and the parameters to your static facelet function. In your case, it would be something like
<h:outputText value="#{my:doStuff(object,10)}" ></h:outputText>
and your facelet function would be
public static String doStuff( MyType o, int param )
{
return o.test( param );
}
Then, using the information in the facelets docbook you would define your function in your taglib.xml file.
It's not the prettiest solution, especially if you plan on doing this a lot, but I believe the next version of the EL (in java EE 6) will allow for using parameters in some cases.
Edit: Some info about parameterized method calls in the next version of el can be found on Ryan Lubke's Blog
I find a sad solution but it's working. I overload a map like this:
new AbstractMap<Integer, String>()
{
#Override
public Set<Entry<Integer, String>> entrySet()
{
return null;
}
#Override
public String get(final Object arg0)
{
Integer keywordDb = (Integer)arg0;
GregorianCalendar cal = new GregorianCalendar(TimeZone.getTimeZone("GMT"));
HashMap<String, String> params = new HashMap<String, String>();
params.put("keywordDb", keywordDb.toString());
params.put("month", new Integer(cal.get(Calendar.MONTH) + 1).toString());
params.put("year", new Integer(cal.get(Calendar.YEAR)).toString());
DataAnalyzeManager manager = new DataAnalyzeManager();
manager.setEm(modelPosition.getEm());
DataAnalyze data = manager.findDataByParams(params, modelPosition.getSite(), false, DataAnalyzeManager.VISITBYMONTHBYKEYWORD);
if (data != null)
return data.getDataInt().toString();
return "0";
}
};
Thereby, I can do that in my JSF:
#{homePositionController.visitByMonth[keyword.keyword.keywordDb]}
And my function is executed.
You may have to have <%# page isELIgnored ="false" %>
at the top of your pages. Read more here. The default is to ignore el expressions. What version of the JSP spec are you using with JSF? If you are using JSF 2 with JSP < 2.1 you are going to run into problems.
Also, what version of el are you using? You can't pass method params with older versions.
<dependency>
<groupId>javax.el</groupId>
<artifactId>el-api</artifactId>
<version>2.1.2-b05</version>
</dependency>
There is couple ways about doing that, you could use JBoss EL expression implementation they support method calls with parameters check out Seam, or use similar approach as #digitaljoel suggested.
This is what I created for that purpose, you can call static and static methods, not a great solution but it does the job.
<c:if test="#{t:call(null, '#Util.SecurityUtility', 'isPanelWorkbookEnabledForUser','')}">
Hello Panel
</c:if>
#Util is just an alias to com.mycomp.util where
Example 2
<c:if test="#{item != null and t:call(item, 'java.lang.String', 'indexOf', t:params(t:param('flash-alert',''))) == 0}">
#{t:call(session, 'org.apache.catalina.session.StandardSessionFacade', 'removeAttribute', t:params(t:param(item,'')))}
</c:if>
Syxtax
java.lang.Object call(java.lang.Object, java.lang.String, java.lang.String, java.lang.Object[])
Where Object is object we want to invoke method on, String is the method name, Object[] are parameters to pass.
t:call, t:params, t:param are function defined in project-taglib.xml as so
<function>
<function-name>call</function-name>
<function-class>util.Functions</function-class>
<function-signature>java.lang.Object call(java.lang.Object, java.lang.String, java.lang.String, java.lang.Object[])</function-signature>
</function>
<function>
<function-name>param</function-name>
<function-class>.util.Functions</function-class>
<function-signature>java.lang.String param(java.lang.Object, java.lang.String)</function-signature>
</function>
<function>
<function-name>params</function-name>
<function-class>util.Functions</function-class>
<function-signature>java.lang.Object[] params(java.lang.String)</function-signature>
</function>
Here is the implementation
package mycompany.web.util;
import java.beans.XMLDecoder;
import java.beans.XMLEncoder;
import java.io.BufferedOutputStream;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.ObjectOutputStream;
import java.io.StringWriter;
import java.lang.reflect.Array;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import javax.el.MethodNotFoundException;
public class Functions {
private static HashMap<String, String> alliasMap;
static{
alliasMap=new HashMap<String, String>();
alliasMap.put("#DateUtil", "com.americanbanksystems.compliance.util.DateUtil");
//Match anything following the dot(.)
alliasMap.put("#Util.*", "com.americanbanksystems.compliance.util");
alliasMap.put("#Application.*", "com.americanbanksystems.compliance.application");
}
public static String param(Object obj, String cls) {
//make sure that passed in object is not null
if(obj==null){
obj="";
}
ByteArrayOutputStream baut=new ByteArrayOutputStream();
XMLEncoder encoder=new XMLEncoder( baut );
//Bug in the JDK
//http://bugs.sun.com/bugdatabase/view_bug.do;jsessionid=c993c9a3160fd7de44075a2a1fa?bug_id=6525396
if(obj instanceof java.sql.Timestamp){
Date o = new Date(((java.sql.Timestamp)obj).getTime());
obj=o;
}
//Checking if this is possible
if(String.class.isAssignableFrom(obj.getClass())){
//removed trailing +" " because it was causing indexOf return invalid value
//Unknown side effects
obj=FacesUtil.get(obj.toString());
}
encoder.writeObject( obj );
encoder.close();
return new String(baut.toByteArray());
}
private static Object decode(String str){
ByteArrayInputStream bais=new ByteArrayInputStream(str.getBytes());
XMLDecoder decoder=new XMLDecoder(bais);
return decoder.readObject();
}
public static Object[] params(String str){
// (?<=</java>)\s*(?=<?)
String[] obj=str.split("(?<=</java>)\\s*(?=<?)");
Object[] results=new Object[obj.length];
for(int i=0;i<obj.length;i++){
results[i]=decode(obj[i]);
}
return results;
}
#SuppressWarnings("unchecked")
public static Object call(Object owningObject, String qualifiedClassname, String methodName, java.lang.Object... methodArguments) {
if (null == methodName || methodName.equals("")) {
throw new IllegalArgumentException("Method name can't be null or empty");
}
if (null == methodArguments) {
methodArguments = new Object[0];
}
//Check for aliases
if(qualifiedClassname.indexOf("#")>-1){
String subpackage=qualifiedClassname;
String originalClass=qualifiedClassname;
//Split at the dot
boolean isPackageAllias=false;
String[] sp=subpackage.split("\\.");
if(sp.length>1){
subpackage=sp[0]+".*";
isPackageAllias=true;
}
if(alliasMap.containsKey(subpackage)){
String value = alliasMap.get(subpackage);
if(isPackageAllias){
qualifiedClassname=subpackage.replace(sp[0], value);
qualifiedClassname=qualifiedClassname.replace(".*", originalClass.replace(sp[0],""));
}else{
qualifiedClassname=value;
}
}else{
throw new IllegalArgumentException("Allias name '"+qualifiedClassname+"' not found");
}
}
Class clazz;
try {
clazz = Class.forName(qualifiedClassname);
//Find method by methodName,Argument Types
Class[] argumentTypes=new Class[methodArguments.length];
for(int i=0;i<methodArguments.length;i++){
argumentTypes[i]=methodArguments[i].getClass();
//Check if the passed in method argument is a string and if its represented as unicode char
//if it is then convert it into a char and reassign to the original parameter
//example 1: \u0022 == "
//example 2: \u0027 == '
// Reason for this functionality is that we can't pass " and ' from within t:call method
if (argumentTypes[i] == String.class && methodArguments[i].toString().indexOf("\\u") > -1) {
String arg = methodArguments[i].toString();
arg = arg.substring(2, arg.length());
try {
int outchar = Integer.parseInt(arg, 16);
if (Character.isDefined(outchar)) {
methodArguments[i] = String.valueOf((char) outchar);
}
} catch (NumberFormatException nfe) {
// Suppress error and continue assuming this is a regular string
}
}
}
Method methodToInvoke = null;
try{
methodToInvoke = clazz.getMethod(methodName, argumentTypes);
}catch(NoSuchMethodException nsm){//Find by method name/ argument count
for (Method method : clazz.getMethods()) {
if (method.getName().equals(methodName) && method.getParameterTypes().length == methodArguments.length) {
if (null == owningObject) {
owningObject = clazz.newInstance();
}
methodToInvoke=method;
break;
}
}
}
if(methodToInvoke!=null){
return methodToInvoke.invoke(owningObject, methodArguments);
}else{
throw new InstantiationException("method not found :" + methodName);
}
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
} catch (InstantiationException e) {
e.printStackTrace();
}
return null;
}
public static void main(String[] arg) {
// StringBuffer buff=new StringBuffer();
// buff.append("Gregs init");
// Functions.call(java.lang.Class<T>, T, java.lang.String, java.lang.String, java.lang.Object...)
/*
* Functions.call(StringBuffer.class, buff, "java.lang.StringBuffer","append"," Init ");
* Functions.call(StringBuffer.class, buff, "java.lang.StringBuffer","append"," greg ");
* System.out.println("output="+ buff);
*/
//#{t:call(null, ".util.DateUtil", "normalizeDate", t:parametize(editRiskActionPlan.riskActionPlan.completionDate,",","java.lang.Object"))}
// c(call(null, "util.DateUtil", "normalizeDate", new Date()));
// #{t:parametize(editRiskActionPlan.riskActionPlan.completionDate,",","java.lang.Object")}
//parametize((new Date()).toString(),",","java.lang.Object");
Date a=new Date();
Date b=new Date();
String rawString=param((Date)b, Date.class.toString() );
//System.out.println(rawString);
//Replaced=#{t:call("Gregs ' car", 'java.lang.String', 'replace', t:params( parameter ))}
String paramA=param("\\u0027","");
String paramB=param("\\u0022","");
String params=paramA+paramB;
String in="I need to ' have a replaced single quote with double";
String out=(String)call(in, "java.lang.String", "replace", params(params));
System.out.println(out);
/*
Object[] obj=params(rawString);
for(Object o:obj){
System.out.println(o);
}
//c(call(null, "#DateUtil", "normalizeDate", obj));
*/
}
}
I hope this helps, btw this was copied/pasted from my project so not sure if I missed anything.
Related
I have written a custom rest Service on an Xpage, which is tied to a bean. The Xpage is:
<xe:restService
id="restServiceCustom"
pathInfo="custom"
ignoreRequestParams="false"
state="false"
preventDojoStore="true">
<xe:this.service>
<xe:customRestService
contentType="application/json"
serviceBean="XXXX.PCServiceBean">
</xe:customRestService>
</xe:this.service>
</xe:restService>
I cobbled together my java agent from some excellent posts around the net. I have just started on the GET. My code runs but I it seems pretty slow (on my dev server). I want to make it as fast as possible. I am using a ViewEntryCollection and I am "flushing" at each record which I assume is streaming.
I am putting my own "[" in the code, so I assume that I am not doing something right, as I never saw any examples of anyone else doing this.
Any suggestions would be greatly appreciated.
package com.XXXXX.bean;
import java.io.IOException;
import java.io.Writer;
import java.util.Vector;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.openntf.domino.Database;
import org.openntf.domino.Session;
import org.openntf.domino.View;
import org.openntf.domino.ViewEntry;
import org.openntf.domino.ViewEntryCollection;
import org.openntf.domino.utils.Factory;
import com.ibm.commons.util.io.json.JsonException;
import com.ibm.commons.util.io.json.util.JsonWriter;
import com.ibm.domino.services.ServiceException;
import com.ibm.domino.services.rest.RestServiceEngine;
import com.ibm.xsp.extlib.component.rest.CustomService;
import com.ibm.xsp.extlib.component.rest.CustomServiceBean;
public class PCServiceBean extends CustomServiceBean {
#Override
public void renderService(CustomService service, RestServiceEngine engine) throws ServiceException {
try {
HttpServletRequest request = engine.getHttpRequest();
HttpServletResponse response = engine.getHttpResponse();
response.setHeader("Content-Type", "application/json; charset=UTF-8");
String method = request.getMethod();
if (method.equals("GET")) {
this.doGet(request, response);
} else if (method.equals("POST")) {
this.doPost(request, response);
} else if (method.equals("PUT")) {
this.doPut(request, response);
} else if (method.equals("DELETE")) {
this.doDelete(request, response);
}
} catch (Exception e) {
throw new RuntimeException(e);
}
}
private void doDelete(HttpServletRequest request, HttpServletResponse response) {
// TODO Auto-generated method stub
}
private void doPut(HttpServletRequest request, HttpServletResponse response) {
// TODO Auto-generated method stub
}
private void doPost(HttpServletRequest request, HttpServletResponse response) {
// TODO Auto-generated method stub
}
private void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException, JsonException {
Session session = Factory.getSession();
Database DB = session.getDatabase(session.getCurrentDatabase().getServer(), "scoApps\\PC\\PCData.nsf");
View pcView = DB.getView("viewAllByStatus");
int i = 1;
Writer out = response.getWriter();
JsonWriter writer = new JsonWriter(out, false);
writer.out("[");
ViewEntryCollection vec = pcView.getAllEntries();
int count = vec.getCount();
for (ViewEntry entry : vec) {
Vector<?> columnValues = entry.getColumnValues();
writer.startObject();
writer.startProperty("unid");
writer.outStringLiteral(String.valueOf(columnValues.get(1)));
writer.endProperty();
writer.startProperty("status");
writer.outStringLiteral(String.valueOf(columnValues.get(0)));
writer.endProperty();
writer.startProperty("assetTag");
writer.outStringLiteral(String.valueOf(columnValues.get(2)));
writer.endProperty();
writer.startProperty("serialNumber");
writer.outStringLiteral(String.valueOf(columnValues.get(3)));
writer.endProperty();
writer.startProperty("model");
writer.outStringLiteral(String.valueOf(columnValues.get(4)));
writer.endProperty();
writer.startProperty("currentLocation");
writer.outStringLiteral(String.valueOf(columnValues.get(5)));
writer.endProperty();
writer.endObject();
if (i != count) {
i = i + 1;
writer.out(",");
writer.flush();
}
}
writer.out("]");
writer.flush();
}
}
Change your code to
JsonWriter writer = new JsonWriter(out, false);
writer.startArray();
ViewEntryCollection vec = pcView.getAllEntries();
int count = vec.getCount();
for (ViewEntry entry : vec) {
Vector<?> columnValues = entry.getColumnValues();
writer.startArrayItem();
writer.startObject();
writer.startProperty("unid");
writer.outStringLiteral(String.valueOf(columnValues.get(1)));
writer.endProperty();
...
writer.endObject();
writer.endArrayItem();
}
writer.endArray();
writer.flush();
It uses JsonWriter's
startArray() and endArray() instead of out("[") and out("]")
startArrayItem() and endArrayItem() instead of out(",") and flush()
The JSON response string gets shorter if you set JsonWriter's compact option to true:
JsonWriter writer = new JsonWriter(out, true);
I see two problems.
First - use ViewNavigator. Here's good explanation of its performance gain.
https://www.mindoo.com/web/blog.nsf/dx/17.01.2013085308KLEB9S.htm
Second - prepare your JSON in advance. This is very good technique to avoid unnecessary code (and time to process it) to get JSON data from Domino documents.
https://quintessens.wordpress.com/2015/09/05/working-with-json-in-your-xpages-application/
How to navigate to the next page based on the return value from the method called inside the action attribute of the command button.
<af:button id="tt_b2"
rendered="#{attrs.nextRendered}"
partialSubmit="true"
action="#{attrs.backingBean.nextAction}"
text="Next"
disabled="#{attrs.nextDisabled}"/>
private static final String NEXT_NAVIGATION_ACTION = "controllerContext.currentViewPort.taskFlowContext.trainModel.getNext";
public String nextAction() {
if (validate()) {
updateModel();
return NEXT_NAVIGATION_ACTION;
}
return null;
}
The use case is done for train model, which is implemented based on this blog : http://javacollectibles.blogspot.co.uk/2014/10/adf-train-template.html
We need to define a generic next action in the template but the action should be called conditionally, based on whether all the validation checks has been passed on not.
Try using ADFUtils.invokeEl
public String nextAction() {
if (validate()) {
updateModel();
return (String)ADFUtils.invokeEL(NEXT_NAVIGATION_ACTION);
}
return null;
}
Its ain't necessary to hardcode any steps, you can query TaskFlowTrainModel
/**
* Navigates to the next stop in a train
* #return outcome string
*/
public String navigateNextStop() {
String nextStopAction = null;
ControllerContext controllerContext = ControllerContext.getInstance();
ViewPortContext currentViewPortCtx = controllerContext.getCurrentViewPort();
TaskFlowContext taskFlowCtx = currentViewPortCtx.getTaskFlowContext();
TaskFlowTrainModel taskFlowTrainModel = taskFlowCtx.getTaskFlowTrainModel();
TaskFlowTrainStopModel currentStop = taskFlowTrainModel.getCurrentStop();
TaskFlowTrainStopModel nextStop = taskFlowTrainModel.getNextStop(currentStop);
//is either null or has the value of outcome
return nextStopAction;
}
Full code of the sample can be found on the ADF Code Corner.
To navigate by taskflow outcomes you just need to provide exact outcome String as return of your method:
private static final String NEXT_NAVIGATION_ACTION = "next";
public String nextAction() {
if (validate()) {
updateModel();
return NEXT_NAVIGATION_ACTION;
}
return null;
}
Can you verify, you can do it in through phase listener.
Verify you condition in the phase listener and allow it to move ahead if it validates else stop the thread execution.
Below is the sample phase listener code.
public class MyPhaseListener implements PagePhaseListener{
public MyPhaseListener() {
super();
}
#Override
public void afterPhase(PagePhaseEvent pagePhaseEvent) {
if (pagePhaseEvent.getPhaseId() == Lifecycle.PREPARE_RENDER_ID ) {
// DO your logic here
}
}
#Override
public void beforePhase(PagePhaseEvent pagePhaseEvent) {
}
}
I'm would like to use MOXy to marshal / unmarshal object from existing classes.
I would like to know if there is a mean to generate XML binding files (cause I don't want to use annotations) from my classes.
Or do we have to do it all with our little hands :) ?
By default JAXB/MOXy doesn't require any metadata to be specified (see: http://blog.bdoughan.com/2012/07/jaxb-no-annotations-required.html). You only need to specify the metadata where you want to override the default behaviour.
I'm guessing your real question is what is the easiest way to create the MOXy external mapping document. I do the following with Eclipse, there are probably similar steps for your favourite IDE:
Get the XML Schema for MOXy's mapping document
<EclipseLink_Home>/xsds/eclipselink_oxm_2_5.xsd
Register the XML Schema with your IDE
Eclipse | Preferences | XML | XML Catalog | Add
Create and XML document in the IDE and specify the following as the root element.
<xml-bindings xmlns="http://www.eclipse.org/eclipselink/xsds/persistence/oxm"/>
Use the auto-complete functionality offered by your IDE to construct the XML document.
Another option is to generate jaxb classes and from those read the bindings (annotations) producing an external mapping (after which you can remove the annotations). PoC code:
public class MoxyBindingGenerator {
private static final String PACKAGE = "com.company.binding.jaxbclasses";
private static ObjectFactory xmlBindingsFactory = new ObjectFactory();
public static void main(String[] args) throws Exception {
Collection<TypeInfo> typeInfos = readAnnotations();
XmlBindings xmlBindings = xmlBindingsFactory.createXmlBindings();
xmlBindings.setPackageName(PACKAGE);
JavaTypes javaTypes = xmlBindingsFactory.createXmlBindingsJavaTypes();
xmlBindings.setJavaTypes(javaTypes);
List<JavaType> javaTypesList = javaTypes.getJavaType();
XmlEnums xmlEnums = xmlBindingsFactory.createXmlBindingsXmlEnums();
xmlBindings.setXmlEnums(xmlEnums);
List<XmlEnum> xmlEnumsList = xmlEnums.getXmlEnum();
typeInfos.stream().forEach(typeInfo -> {
if (!typeInfo.isEnumerationType()) {
fillJavaTypes(javaTypesList, typeInfo);
}
else {
fillEnumTypes(xmlEnumsList, typeInfo);
}
});
saveToFile(xmlBindings);
}
private static Collection<TypeInfo> readAnnotations() throws JAXBException, Exception {
JAXBContext jaxbContext = (JAXBContext) javax.xml.bind.JAXBContext.newInstance(PACKAGE);
Object contextState = getPrivateField(jaxbContext, "contextState");
Generator generator = (Generator) getPrivateField(contextState, "generator");
AnnotationsProcessor annotationsProcessor = generator.getAnnotationsProcessor();
Collection<TypeInfo> typeInfos = annotationsProcessor.getTypeInfo().values();
return typeInfos;
}
private static void fillEnumTypes(List<XmlEnum> xmlEnumsList, TypeInfo typeInfo) {
EnumTypeInfo et = (EnumTypeInfo) typeInfo;
XmlEnum xmlEnum = xmlBindingsFactory.createXmlEnum();
xmlEnum.setJavaEnum(et.getJavaClassName());
List<String> xmlEnumNames = et.getFieldNames();
List<Object> xmlEnumValues = et.getXmlEnumValues();
for (int i = 0; i < xmlEnumNames.size(); i++) {
String xmlEnumName = xmlEnumNames.get(i);
Object xmlEnumObject = xmlEnumValues.get(i);
XmlEnumValue xmlEnumValue = xmlBindingsFactory.createXmlEnumValue();
xmlEnumValue.setJavaEnumValue(xmlEnumName);
xmlEnumValue.setValue(xmlEnumObject.toString());
xmlEnum.getXmlEnumValue().add(xmlEnumValue);
}
xmlEnumsList.add(xmlEnum);
}
private static void fillJavaTypes(List<JavaType> javaTypesList, TypeInfo typeInfo) {
JavaType javaType = xmlBindingsFactory.createJavaType();
javaType.setName(typeInfo.getJavaClassName());
fillXmlType(javaType, typeInfo);
if (typeInfo.getXmlRootElement() != null) {
XmlRootElement xmlRootElement = typeInfo.getXmlRootElement();
xmlRootElement.setNamespace(null);
javaType.setXmlRootElement(xmlRootElement);
}
JavaAttributes javaAttributes = xmlBindingsFactory.createJavaTypeJavaAttributes();
javaType.setJavaAttributes(javaAttributes);
List<JAXBElement<? extends JavaAttribute>> javaAttributeList = javaAttributes.getJavaAttribute();
typeInfo.getNonTransientPropertiesInPropOrder().stream().forEach(field -> {
fillFields(javaAttributeList, field);
});
javaTypesList.add(javaType);
}
private static void fillFields(List<JAXBElement<? extends JavaAttribute>> javaAttributeList, Property field) {
if (field.getXmlElements() != null && field.getXmlElements().getXmlElement().size() > 0) {
XmlElements xmlElements = xmlBindingsFactory.createXmlElements();
xmlElements.setJavaAttribute(field.getPropertyName());
List<XmlElement> elements = field.getXmlElements().getXmlElement();
elements.stream().forEach(e -> {
e.setDefaultValue(null);
e.setNamespace(null);
xmlElements.getXmlElement().add(e);
});
JAXBElement<XmlElements> value = xmlBindingsFactory.createXmlElements(xmlElements);
javaAttributeList.add(value);
}
else if (!field.isAttribute()) {
XmlElement value = xmlBindingsFactory.createXmlElement();
value.setJavaAttribute(field.getPropertyName());
value.setName(field.getSchemaName().getLocalPart());
if (field.isNillable())
value.setNillable(field.isNillable());
if (field.isRequired())
value.setRequired(field.isRequired());
javaAttributeList.add(xmlBindingsFactory.createXmlElement(value));
}
else {
XmlAttribute value = xmlBindingsFactory.createXmlAttribute();
value.setJavaAttribute(field.getPropertyName());
value.setName(field.getSchemaName().getLocalPart());
javaAttributeList.add(xmlBindingsFactory.createXmlAttribute(value));
}
}
private static void saveToFile(XmlBindings xmlBindings)
throws JAXBException, PropertyException, FileNotFoundException, IOException {
JAXBContext xmlModelJaxbContext =
(JAXBContext) javax.xml.bind.JAXBContext.newInstance("org.eclipse.persistence.jaxb.xmlmodel");
JAXBMarshaller marshaller = xmlModelJaxbContext.createMarshaller();
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
FileOutputStream fos = new FileOutputStream(new File(System.getProperty("user.home"), "binding-imspoor-oxm.xml"));
marshaller.marshal(xmlBindings, fos);
fos.close();
}
private static void fillXmlType(JavaType javaType, TypeInfo typeInfo) {
XmlType orgXmlType = typeInfo.getXmlType();
if (orgXmlType != null) {
boolean add = false;
XmlType xmlType = xmlBindingsFactory.createXmlType();
if (!StringUtils.isEmpty(orgXmlType.getName())) {
xmlType.setName(orgXmlType.getName());
add = true;
}
if (orgXmlType.getPropOrder() != null && orgXmlType.getPropOrder().size() > 1) {
xmlType.getPropOrder().addAll(orgXmlType.getPropOrder());
add = true;
}
if (add)
javaType.setXmlType(xmlType);
}
}
private static Object getPrivateField(Object obj, String fieldName) throws Exception {
Field declaredField = obj.getClass().getDeclaredField(fieldName);
declaredField.setAccessible(true);
return declaredField.get(obj);
}
}
I have
public class ExtendedBeanELResolver extends BeanELResolver {
private static final Pattern regExpDn = Pattern.compile("PLMN-PLMN/\\w+.\\d+(.*)");
#Override
public Object getValue(ELContext context, Object base, Object property)
try {
// remake DIST.NAME appearance
if (property.equals("dn") && base instanceof Alarm && ((Alarm) base).getCustomer().getNameEng().equalsIgnoreCase("mts")) {
String dn = null;
try {
dn = ((Alarm) base).getDn();
Matcher mtch = regExpDn.matcher(dn);
mtch.find();
((Alarm) base).setDn(mtch.group(1));
} catch (Throwable e) {
// logger.error("error in dn - " + dn);
} finally {
return super.getValue(context, base, property);
}
}
}
for change some visible values in object depending on some conditions. I do not want to change value if this called from jsf <ui:param name="fullDistName" value="#{alarm.dn}" />
How i can get id of component from which this EL called?
sorry for my english.
You can get the current JSF component by programmatically evaluating #{component} or by invoking UIComponent#getCurrentComponent().
UIComponent component = UIComponent.getCurrentComponent(FacesContext.getCurrentInstance();
// ...
Please note that this tight-couples your EL resolver to JSF.
i have an managed bean(session scope) like this:
class Home {// as homeBean
public void doSomething(ActionEvent ae, int a, int b){
System.out.println("result="+(a+b));
}
}
i like to call this
<a4j:commandLink actionListener="#{homeBean:doSomething(1,2)}"/>
what i know is: it isnt possible to use a and b parameter.
ok: this should be in example a "static" possibility to invoke this using an taglib:
public class CoolTaglib implements TagLibrary{
...
public static void doSomething(int a, int b) {
getHomeBeanFromSession().doSomething(a,b);
}
}
what about to invoke it dynamicly? using bcel or URLClassLoader?
This EL expression syntax is for static methods only and must be defined in a tag library and have the namespace defined in the view:
#{namespacePrefix:fn(arg)}
This EL expression with invokes a parameterized method on an object instance:
#{someInstance.method(arg)}
The second form is available in Expression Language 2.2 or above (Java EE 6.) Similar expressions are supported in some 3rd party JSF libraries prior to this.
It is possible to look up a managed bean from a static method so long as it is executed within a JSF context:
FacesContext context = FacesContext.getCurrentInstance();
SomeBean someBean = context.getApplication()
.evaluateExpressionGet(context,
"#{someBean}", SomeBean.class);
This is not the ideal approach however. This code was written against JSF 2; prior versions use different dynamic lookup calls.
If you need a bean in a static method, use an expression of the form:
#{namespacePrefix:fn(someBean, 1, 2)}
Oh cool, i found a way to work:
public class ... implements TagLibrary {
#Override
public Method createFunction(String taglib, String functionName) {
if (!map.containsKey(functionName)) {
String classname = "de.Test" + functionName;
ClassGen _cg = new ClassGen(classname,
"java.lang.Object", "Test.java", ACC_PUBLIC | ACC_SUPER,
new String[] {});
ConstantPoolGen _cp = _cg.getConstantPool();
InstructionFactory _factory = new InstructionFactory(_cg, _cp);
Method meth = find(functionName, getNavigation());
Class<?>[] parameterTypes = meth.getParameterTypes();
int countParams = parameterTypes.length;
Type[] types = new Type[countParams];
String[] names = new String[countParams];
for (int i = 0; i < countParams; i++) {
types[i] = new ObjectType(parameterTypes[i].getName());
names[i] = "arg" + i;
}
InstructionList il = new InstructionList();
MethodGen staticMethod = new MethodGen(ACC_PUBLIC | ACC_STATIC,
Type.OBJECT, types, names, functionName, getClass()
.getName(), il, _cp);
InstructionHandle ih_1 = il.append(new PUSH(_cp, functionName));
il.append(new PUSH(_cp, countParams));
il.append(_factory.createNewArray(Type.OBJECT, (short) 1));
il.append(InstructionConstants.DUP);
for (int i = 0; i < countParams; i++) {
il.append(new PUSH(_cp, i));
il.append(_factory.createLoad(Type.OBJECT, i));
il.append(InstructionConstants.AASTORE);
if (i != countParams - 1)
il.append(InstructionConstants.DUP);
}
il.append(_factory.createInvoke(getClass().getName(),
"call", Type.OBJECT, new Type[] { Type.STRING,
new ArrayType(Type.OBJECT, 1) },
Constants.INVOKESTATIC));
InstructionHandle ih_25 = il.append(_factory
.createReturn(Type.OBJECT));
staticMethod.setMaxStack();
staticMethod.setMaxLocals();
_cg.addMethod(staticMethod.getMethod());
il.dispose();
try {
byte[] bytes = _cg.getJavaClass().getBytes();
InjectingClassLoader icl = new InjectingClassLoader();
Method find =
find(functionName, icl.load(classname, bytes));
map.put(functionName, find);
} catch (Exception e) {
e.printStackTrace();
}
}
Method method = map.get(functionName);
return method;
}
public static Object call(String functionname, Object[] arguments) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException {
Navigation myTargetBean = getNavigation();
Method proxyMethod = find(functionname,myTargetBean);
Object result = proxyMethod.invoke(myTargetBean, arguments);
return result;
}
Now, i am able to call #{cms:doSomething(1,2)}