Is there a way to generate a XML binding file from a class using MOXy? - jaxb

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);
}
}

Related

Spring integeration DefaultSoapHeaderMapper - getStandardRequestHeaderNames - override

in previous si versions (si 2.11 to be specific and spring 3.1.1) getStandardRequestHeaderNames could be overrided to include Additional Application specific objects in the si message header. Our application relied on this ability (may be wrongfully so) to override this method and supply a custom POJO to be carried downstream consisting of many splitters, aggregators etc. The app used an ws inbound gateway and used the header-mapper attribute to specify the custom soap header mapper.
Any clues on the reasoning behind why getStandardRequestHeaderNames cannot be overriden?
Need some advise on how I can migrate this to the current spring release.
The requirement is to extract elements from soapHeader and map them to an SI message headers as an POJO and send it down stream.
All help appreciated.
Code Snippet: Works with older versions of spring
<int-ws:inbound-gateway id="webservice-inbound-gateway"
request-channel="input-request-channel"
reply-channel="output-response-channel"
header-mapper="CustomSoapHeaderMapper"
marshaller="marshaller"
unmarshaller="marshaller" />
#Component("CustomSoapHeaderMapper")
public class CustomSoapHeaderMapper extends DefaultSoapHeaderMapper {
private static final Logger logger = Logger.getLogger("CustomSoapHeaderMapper");
public static final String HEADER_SEARCH_METADATA = SearchMetadata.HEADER_ATTRIBUTE_NAME;
public static final String HEADER_SERVICE_AUDIT = "XXXXXXXX";
// Use simulation if security token is set to this value
public static final String SECURITY_TOKEN_SIMULATION = "XXXX";
private static final List<String> CUSTOM_HEADER_NAMES = new ArrayList<String>();
static {
CUSTOM_HEADER_NAMES.add(WebServiceHeaders.SOAP_ACTION);
CUSTOM_HEADER_NAMES.add(HEADER_SEARCH_METADATA);
}
private int version =SearchMetadata.VERSION_CURRENT;
public void setVersion(int version) {
this.version = version;
}
#Override
protected List<String> getStandardRequestHeaderNames() {
return CUSTOM_HEADER_NAMES;
}
#Override
protected Map<String, Object> extractUserDefinedHeaders(SoapMessage source) {
// logger.log(Level.INFO,"extractUserDefinedHeaders");
// call base class to extract header
Map<String, Object> map = super.extractUserDefinedHeaders(source);
Document doc = source.getDocument();
SearchMetadata searchMetadata = new SearchMetadata();
ByteArrayOutputStream baos = new ByteArrayOutputStream();
try {
source.writeTo(baos);
baos.flush();
searchMetadata.setRequestXML(baos.toString());
baos.close();
} catch (IOException e1) {
}
//logger.log(Level.WARNING, "Incoming Message " + baos.toString());
SOAPMessage soapMessage = ((SaajSoapMessage) source).getSaajMessage();
// generate TransactionID with UUID value
String transactionID = UUID.randomUUID().toString();
// logger.log(Level.WARNING, "TransactionID=" + transactionID);
Date now = new Date();
searchMetadata.setTransactionID(transactionID);
searchMetadata.setRequestType(SearchMetadata.REQUEST_TYPE_SYNCHRONOUS);
searchMetadata.setRequestTime(now);// initialize the request time
searchMetadata.setReceivedTime(now);// mark time system receives request
searchMetadata.setVersion(version);
Map<String, Object> finalHeaders = new HashMap<String, Object>();
finalHeaders.put(HEADER_SEARCH_METADATA, searchMetadata);
if (!CollectionUtils.isEmpty(map)) {
// copy from other map
finalHeaders.putAll(map);
// check if ServiceAudit is available
SoapHeaderElement serviceAuditElement = null;
for (String key : map.keySet()) {
// logger.log(Level.WARNING, "SoapHeader.{0}", key);
if (StringUtils.contains(key, HEADER_SERVICE_AUDIT)) {
serviceAuditElement = (SoapHeaderElement) map.get(key);
break;
}
}
}
return finalHeaders;
}
// GK Key Thing here for performance improvement is avoiding marshalling
public gov.dhs.ice.ess.schema.ServiceAudit ExtractAuditHeader(Document doc) {
....
}
return serviceAudit;
}
}
Share, please, some code how would you like to see that.
Maybe you can just implement your own SoapHeaderMapper and inject it into WS Inbound Gateway?
You can still reuse your logic and copy/paste the standard behavior from the DefaultSoapHeaderMapper.
UPDATE
The test-case to demonstrate how to add user-defined header manually:
#Test
public void testCustomSoapHeaderMapper() {
DefaultSoapHeaderMapper mapper = new DefaultSoapHeaderMapper() {
#Override
protected Map<String, Object> extractUserDefinedHeaders(SoapMessage source) {
Map<String, Object> headers = super.extractUserDefinedHeaders(source);
headers.put("foo", "bar");
return headers;
}
};
mapper.setRequestHeaderNames("*");
SoapMessage soapMessage = mock(SoapMessage.class);
Map<String, Object> headers = mapper.toHeadersFromRequest(soapMessage);
assertTrue(headers.containsKey("foo"));
assertEquals("bar", headers.get("foo"));
}

How to customize com.liferay.portlet.wiki.action.GetPageAttachmentAction using Ext Plugin

I am using Liferay 6.2 and I want to modify GetPageAttachmentAction.
I want to add the following code in strutsExecute to include the title in the file name:
public ActionForward strutsExecute(
ActionMapping actionMapping, ActionForm actionForm,
HttpServletRequest request, HttpServletResponse response)
throws Exception {
long nodeId = ParamUtil.getLong(request, "nodeId");
String title = ParamUtil.getString(request, "title");
String fileName = ParamUtil.getString(request, "fileName");
// Here my change:
int pos = fileName.indexOf(CharPool.SLASH);
if (pos >= 0) {
title = fileName.substring(0, pos);
fileName = fileName.substring(pos + 1);
}
...
If I create a hook plugin for this change by extending BaseStrutsPortletAction with a custom class then it does not provide strutsExecute() to override.
Should I go with an Ext plugin instead? If yes, then suggest me the configuration of the Ext plugin to modify GetPageAttachmentAction.
You can do either: Hook plugin or Ext plugin.
But a hook seems to make more sense here:
public class MyGetPageAttachmentAction extends BaseStrutsPortletAction {
public void processAction(
StrutsPortletAction originalStrutsPortletAction,
PortletConfig portletConfig, ActionRequest actionRequest,
ActionResponse actionResponse)
throws Exception {
String title = ParamUtil.getString(actionRequest, "title");
String fileName = ParamUtil.getString(actionRequest, "fileName");
// Your code:
int pos = fileName.indexOf(CharPool.SLASH);
if (pos >= 0) {
title = fileName.substring(0, pos);
fileName = fileName.substring(pos + 1);
}
// Wrap request to add your new parameters (the original request parameters are immutable)
DynamicActionRequest dynamicActionRequest = new DynamicActionRequest(actionRequest, true);
dynamicActionRequest.setParameter("fileName", fileName);
dynamicActionRequest.setParameter("title", title);
// And delegate to original action
originalStrutsPortletAction.processAction(portletConfig, dynamicActionRequest, actionResponse);
}
}
(From your question I guess that you already have the correct settings in liferay-hook.xml)

How to get list of folders present in a directory in SVN using java

I am using svnkit-1.3.5.jar in my application. On one of my screens on clicking a button I need to display a jQuery dialog box containing list of folders present at a particular path in SVN. Does svnkit provide any method that retrieves all folder names present at a specific location? How do I achieve this in java?
Here is the code i use for the same purpose (uses svnkit library). Modified version of #mstrap's code for better clarity.
public static String NAME = "svnusername";
public static String PASSWORD = "svnpass";
public final String TRUNK_VERSION_PATH = "svn://192.168.1.1/path";
public static List<String> apiVersions;
public List<String> getApiVersion() {
logger.info("Getting API Version list....");
apiVersions = new ArrayList<String>();
SVNURL repositoryURL = null;
try {
repositoryURL = SVNURL.parseURIEncoded(TRUNK_VERSION_PATH);
} catch (SVNException e) {
logger.error(e);
}
SVNRevision revision = SVNRevision.HEAD;
SvnOperationFactory operationFactory = new SvnOperationFactory();
operationFactory.setAuthenticationManager(new BasicAuthenticationManager(NAME, PASSWORD));
SvnList list = operationFactory.createList();
list.setDepth(SVNDepth.IMMEDIATES);
list.setRevision(revision);
list.addTarget(SvnTarget.fromURL(repositoryURL, revision));
list.setReceiver(new ISvnObjectReceiver<SVNDirEntry>() {
public void receive(SvnTarget target, SVNDirEntry object) throws SVNException {
String name = object.getRelativePath();
if(name!=null && !name.isEmpty()){
apiVersions.add(name);
}
}
});
try {
list.run();
} catch (SVNException ex) {
logger.error(ex);
}
return apiVersions;
}
Cheers!!
final URL url = ...
final SVNRevision revision = ...
final SvnOperationFactory operationFactory = ...
final SvnList list = operationFactory.createList();
list.setDepth(SVNDepth.IMMEDIATES);
list.setRevision(revision);
list.addTarget(SvnTarget.fromURL(url, revision);
list.setReceiver(new ISvnObjectReceiver<SVNDirEntry>() {
public void receive(SvnTarget target, SVNDirEntry object) throws SVNException {
final String name = object.getRelativePath();
System.out.println(name);
}
});
list.run();

JSF - CDI instancing again a session bean

The source code:
public class ReportGenerator implements Serializable {
private static final long serialVersionUID = -3995091296520157208L;
#Inject
private ReportCacheSession reportCacheSession;
#Inject
private UserSessionBean userSessionBean;
#Inject
private Instance<ReportBuilder> reportBuilderInstance;
public static final int BUILD_ERROR = 0;
public static final int BUILD_OK = 1;
public static final int BUILD_NOPAGES = 2;
private ReportBuilder reportBuilder = null;
private FileData build(String jasperName, Map<String, Object> params, String extension, boolean guardarCache, boolean inline) {
FileData fd = null;
reportBuilder = reportBuilderInstance.get();
if (reportBuilder != null) {
reportBuilder.jasperName = jasperName;
reportBuilder.emailName = SevUtils.getEmailName(userSessionBean.getUserInfo().getEmail());
reportBuilder.sessionId = JSFUtils.getSessionId();
reportBuilder.params = params;
reportBuilder.extension = extension;
//reportBuilder.config(jasperName, SevUtils.getEmailName(userSessionBean.getUserInfo().getEmail()), JSFUtils.getSessionId(), params, extension);
reportBuilder.start();
try {
reportBuilder.join();
} catch (InterruptedException ex) {
Logger.getLogger(ReportGenerator.class.getName()).log(Level.SEVERE, null, ex);
}
fd = reportBuilder.getFileData();
}
if (fd != null && fd.getState() == BUILD_OK) {
fd.setInline(inline);
if (guardarCache) {
reportCacheSession.addReport(fd);
}
}
return fd;
}
}
reportBuilder.start(); is a new Thread to generate the report(s), the problem is when the line reportCacheSession.addReport(fd); is called CDI create a new instance each time, but ReportCacheSession is a session bean annotated with javax.inject.Named and javax.enterprise.context.SessionScoped.
I don't know why this happens, but my solution is add a new line, like this:
FileData fd = null;
reportCacheSession.toString(); //NEW LINE
reportBuilder = reportBuilderInstance.get();
reportCacheSession.toString(); create the instance of ReportCacheSession before my thread is called and all works OK...
How the new thread affects to CDI? Why CDI created a new instance of my session bean when I called the thread before?
UPDATE 08/15/12:
Ok, I have changed my code to use the EJB annotation #Asynchronous, in this case I have problem when I'm generating a large PDF report (the XLS report works without problem), the file's size is incomplete(less bytes) and when I try to open it this appear in blank... Maybe a problem/bug with JRExporter#exportReport method...
LAST UPDATE:
Ok, the report generation was my mistake... the question is which alternative is best to use EJB Asynchronous or JMS? Thanks to all, each comment have led me to find a good solution...

taglib call to managedbean call

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)}

Resources