I want to create a custom component in JSF and have created it already.Now I want to create attributes for that custom tag that i use in the XHTML file and make them as mandatory.
I have created a component MyJSFComponent extending from UIOutput class. How can i mandate certain attributes?
You don't do that in the UIComponent side, but in the .taglib.xml or TagHandler side.
In the .taglib.xml file you can just add a <required>true</required> entry to the attribute.
<attribute>
<name>foo</name>
<required>true</required>
<type>java.lang.String</type>
</attribute>
You're however dependent on the tooling (the editor) whether this will cause an error or not. JSF/Facelets namely won't check it during runtime. Eclipse for example will automatically inline the attribute when autocompleting the tag in the editor, however it's possible to remove it afterwards and it'll run without errors.
A more solid enforcement is using a ComponentHandler class which offers the getRequiredAttribute() method which would throw TagException when absent. You can then register this handler in .taglib.xml file as follows:
<component>
<component-type>com.example.SomeComponent</component-type>
<handler-class>com.example.SomeComponentHandler</handler-class>
</component>
Whereby the handler class basically look like this:
public class SomeComponentHandler extends ComponentHandler {
public SomeComponentHandler(ComponentConfig config) {
super(config);
getRequiredAttribute("foo");
}
}
This does a real runtime check on the presence of the attribute.
Related
Here is an example of what I'm trying to unmarshall with JAXB:
<?xml version="1.0" encoding="UTF-8"?>
<menus>
<menu>
<name>main</name>
<subMenu>
<name>mainMenu</name>
<!-- Transfer / Versement -->
<subMenu>
<name>transfer</name>
<label>MENU_TRANSFER</label>
<icon>call-received</icon>
<menuItem>
<name>record</name>
<label>MENU_RECORD</label>
<url>/pages/record/search/recordListSearchResult.jsf</url>
</menuItem>
<menuItem>
<name>transferInput</name>
<label>MENU_TRANSFER_OPEN</label>
<url>/pages/transfer/open/transferListOpen.jsf</url>
</menuItem>
</subMenu>
</menu>
</menus>
Once unmarshalled, with java generated code, I want to be able to retrieve the submenu parent of a menuItem (without having to use loop etc.) Basically, I want to generate a getter getParent on MenuItem returning his parent. Is there an easy way to do this?
You can use Unmarshal Event Callbacks to receive parent object in the instance of your mapped class after unmarshalling. To do this simply add a method with the following signature:
void afterUnmarshal(Unmarshaller unmarshaller, Object parent);
Thus you'll get the parent submenu in the child submenu after unmarshalling.
If your mapped classes are schema-derived (for example you compile some XML schema with XJC), you can use the code injector plugin to add code to generated classes.
I also think there should be XJC plugins for handling parent objects (google XJC or JAXB parent plugin).
I have a bindings file with the following content:
<java-type name="JavaType">
<xml-root-element name="root"/>
<java-attributes>
...
</java-attributes>
</java-type>
When I marshall the JavaType class using this binding, the XML looks like this
<root xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="JavaType">
I don't want the xsi:type to be there, how can I suppress this when marshalling?
The xsi:type attribute will appear when you are marshalling a subclass. You can have it be suppressed by wrapping your object in a JAXBElement that supplies information about the root element including type.
JAXBElement<JavaType> je = new JAXBElement(new QName(), JavaType.class javaType);
marshaller.marshal(je, System.out);
Example
Is there a possibility to hide the "#type" entry when marshalling subclasses to JSON using EclipseLink MOXy (JAXB)?
UPDATE
Thanks. I now made the superclass XmlTransient, which makes the
xsi:type disapear as well. I used the annotation to do that. Is there
actually a way to use to make a java-type be
transient? I could only make it work for java-attributes.
You are correct. You can use #XmlTransient at the class level to have it removed from the inheritance hierarchy. Below is how this can be done using MOXy's external mapping document.
<?xml version="1.0" encoding="UTF-8"?>
<xml-bindings
xmlns="http://www.eclipse.org/eclipselink/xsds/persistence/oxm"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
package-name="com.example.foo">
<java-types>
<java-type name="Foo" xml-transient="true"></java-type>
</java-types>
</xml-bindings>
For More Information
http://blog.bdoughan.com/2011/06/ignoring-inheritance-with-xmltransient.html
I tried #blaise-doughan's suggestion and added the #XmlTransient annotation to top of my abstract base class.
With my environment (so my product depends something strictly), the jaxb-api library says "The annotation #XmlTransient is disallowed for this location" because of the version of it high probably older than 2.1. I realized that when I tried to adding the annotation with a new test class-path which contains version >=2.1, so it allows to defining it top of a class.
So let me get straight to the point, I suggest below method in order to get rid of the type fields which appears on responses which are building and marshaling from extended classes.
I only added #XmlDiscriminatorNode("") to top of my base class and I supposed that you are using the EclipseLink MOXy:
import org.eclipse.persistence.oxm.annotations.XmlDiscriminatorNode;
#XmlDiscriminatorNode("")
public abstract class Base {
private int id;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
}
As a summary you can use #XmlTransient if you have the jaxb-api version greater than 2.1 or use my method if you have EclipseLink MOXy.
How do you get a reference to the current ActivePivotManger? I've found code that uses it but no way to actually get ahold of it.
If you look at the class SandboxConfig in last v4.4.x you'll see that this class is annotated as following:
#PropertySource(value="classpath:sandbox.properties")
#Configuration
#Import(value={
ActivePivotConfig.class,
ActivePivotServicesConfig.class,
WebServicesConfig.class,
RemotingConfig.class,
SecurityConfig.class
})
public class SandboxConfig {
The ActivePivotConfig.class in the annotation is the one in which we define the activePivotManager which is defined as a member of the SandboxConfig class:
/** ActivePivot Manager, automatically wired */
#Autowired
protected IActivePivotManager activePivotManager;
The #Autowired here is important as it means that this is provided already.
in the previous versions of AP we were defining this as following in our project:
<!-- ActivePivot Manager -->
<bean id="ActivePivotManager" class="com.quartetfs.biz.pivot.impl.ActivePivotManagerFactory">
<property name="resourceName" value="DESC-INF/ActivePivotManager.xml" />
<property name="autoStart" value="false" />
<property name="healthCheckPeriod" value="120"/>
</bean>
If you want to use the ActivePivotManager instance stick then to what is in the SandboxConfig and add your logic there, use the ActivePivotManager instance defined there.
If you're not happy with that move to full XML wiring which is still supported as I can understand that some stuff is hidden and you expect to see the instance of ActivePivotManager instantiated clearly somewhere (which is done actually in ActivePivotConfig.class).
Mule 3.3 can automatically unmarshall an XML string to an object using JAXB given that:
1. you first register your jaxb annotated classes with spring.
2. there is a component that requires such type as input
So I have managed to do the transformation, but I had to create a "DumbTransformer" that does nothing. It has a method that returns the same object it receives. I need it in order to trigger the XML to Object conversion so that I can further process the message.
Flow Example:
<spring:beans>
<spring:bean id="dumbTransformer" class="foo.bar.DumbTransformer"/>
</spring:beans>
<flow name="main" doc:name="main">
<vm:inbound-endpoint path="in" doc:name="VM" />
<component doc:name="Java">
<spring-object bean="dumbTransformer"/>
</component>
<splitter expression="#[payload.items]" doc:name="Split Items"/>
<logger message="#[payload]" level="INFO" doc:name="Log Item"/>
<vm:outbound-endpoint path="out" doc:name="VM" />
</flow>
DumbTransformer.java
package foo.bar;
#ContainsTransformerMethods
public class InvoiceUnmarshaller extends AbstractTransformer {
#Transformer
public MyJaxbAnnotatedClass foo(#Payload MyJaxbAnnotatedClass i) {
return i;
}
}
Is there a way to acomplish this without having to create such DumbTransformers?
Thanks.
As you guessed it, the JAXB deserialization doesn't occur because there is no component to satisfy:
there is a component that requires such type as input
So what if you had an auto-transformer to do just that:
<auto-transformer returnClass="foo.bar.MyJaxbAnnotatedClass" />
The Mule XML Module provides OOTB a JAXB Transformer. I would rather leverage mule capabilities whenever possible rather than writing custom code
I am trying to register different converter instances in the faces-config, using a standard converter class to which different parameters are passed.
The code below registers two DateTimeConverters, the first one for dates including time and the second one for time only. But the pattern property never gets set. Can this be done?
<converter>
<converter-id>dateTimeConverter</converter-id>
<converter-class>javax.faces.convert.DateTimeConverter</converter-class>
<property>
<property-name>pattern</property-name>
<suggested-value>yyyy-MM-dd HH:mm:ss</suggested-value>
</property>
</converter>
<converter>
<converter-id>timeConverter</converter-id>
<converter-class>javax.faces.convert.DateTimeConverter</converter-class>
<property>
<property-name>pattern</property-name>
<suggested-value>HH:mm:ss</suggested-value>
</property>
</converter>
This is unfortunately not possible through faces-config.xml. The <property> declaration which you're trying is not used during runtime.
If all you want is to control the pattern at one place, then best what you can do is to create a custom converter. For this particular purpose it isn't that hard. Just extend DateTimeConverter and set the pattern during construction. Here's a basic example:
public MyDateTimeConverter extends DateTimeConverter() {
public MyDateTimeConverter() {
setPattern("yyyy-MM-dd HH:mm:ss");
}
}
You can of course get the pattern from somewhere else, e.g. a properties file or xml file in classpath.
Register this converter as follows:
<converter>
<converter-for-class>java.util.Date</converter-for-class>
<converter-class>com.example.MyDateTimeConverter</converter-class>
</converter>
That should be it. No need for f:converter or UIOutput#setConverterId().