How to get a specific custom converter from DozerBeanMapperFactoryBean? - java

I am working on a particular task which consisters of different phases. In the first phase I created a class(a) that reads a property file and saves the data into a hashmap. This class has a method (1) that will get the key and return the corresponding value from the map, if there is no entry in the map the key enter will be returned.
In the second phase I created a custom converter class (b)the extends the DozerConverter class I then autowired class (a) and in the method convertTo() that is provided by the DozerConverter class I simpley call the method (1) of class (a).
Since I am using Spring I have used the following code
#Bean
public DozerBeanMapperFactoryBean configDozer() throws IOException {
DozerBeanMapperFactoryBean mapper = new DozerBeanMapperFactoryBean();
mapper.setCustomConverters(Collections.<CustomConverter> singletonList(new ErrorCodeConverter()));
return mapper;
}
The part that I am confused about is how can I get the ErrorCodeConverter from the mapper object and use this class which is my custom converter. I have found lots of examples where they provide xml mappings but I don't want any xml mapping. This job is being done for me by class (a). I have wrapped class (a) with custom converter to make using of dozzer mapper api.
Any help will be highly appreciated.

I just take a look in Dozer code from my local (5.3.1), it appears Dozer is designed to apply Custom Converter at 'field' level not 'class' level through API.
You can tweak a bit which wrap your object as a field of another class so you can use API to perform CustomConverter. Hope it helps.
Nghia

Related

Spring create list of beans based on properties

In a simple Spring boot application I have my component like this:
#Data
#Component
public class GenericHandler {
private String path;
private HandlerType type;
}
And my properties might look like this:
my.handlers[0].path='/vol1/abc'
my.handlers[0].type='Single'
my.handlers[1].path='/vol1/dora'
my.handlers[1].type='MultiSequence'
I tried decorating with the GenericHandler-class with #ConfigurationProperties(prefix="my.handlers") and getting a list of all component instances in a service using
#Autowired
private List<GenericHandler> handlers;
But that created just one component, ignoring the property values at all.
How can I get one component instance per my.handlers property-entry?
You need a wrapper class
#Component
#ConfigurationProperties(prefix="my.handlers")
#Data
public class GenericHandlerWrapper {
private List<GenericHandler> handlers;
...
}
Then you can autowire the GenericHandlerWrapper
Update
As #zoolway pointed out in the comments, for the properties in the question to work as it is, #ConfigurationProperties(prefix="my.handlers") should be changed to #ConfigurationProperties(prefix="my")
That's not possible. What can be done is this:
#Data
#Component
public class GenericHandler {
private List<String> path;
private List<HandlerType> type;
}
I dealt with a similar issue in a different manner. I created a factory and an interface. The factory would hold different implementations of that interface In your case, GenericHandler would be your interface. Then you write any number of implementations of your interface and each implementation is declared as a Component. So, Spring will instantiate it as bean upon a startup (you might use #Lazy(false) to force the instantiation at startup) using some infrastructure that I wrote each bean of that interface will self-insert itself into its factory. Then at any part of your code in any bean, you can use the factory to access concrete implementation (base on your property "type" for example). The beauty is that you don't need to inject all the implementations in your bean at the time of writing but access needed implementation dynamically at run-time. I found this to be a useful pattern and created an infrastructure that does most of the work for you and published it as an Open Source library called MgntUtils. The detailed description of the idea (including reference to the library) could be found here. Also detailed explanation with examples of how to use it can be found in library Javadoc here. The library is available (with source code and Javadoc) as Maven artifacts and on the Github. Also a general article about the MgntUtils library could be found here

MapStruct: Object.class to Custom.class mapping

I'm a newbie with MapStruct, and need some help with that.
I have a Source class, with an attribute
Object input;
Which, in runtime, returns a custom object named TicketDetails.
Now, in my target class there is a attribute named,
MyTicket myTicket;
which, I need to map with an attribute of TicketDetails object.
For, better understanding, I'm writing the normal java code example below.
SourceClassModel sourceClassModel = new SourceClassModel();
TargetClassModel targetClassModel = new TargetClassModel();
//mapping
TicketDetails ticketDetails = (TicketDetails) sourceClassModel.getInput();
targetClassModel.setMyTicket(ticketDetails.getMyTicket);
Now, my question is, how to achieve this case using MapStruct?
Either on a used mapper (see #Mapper#uses()) or in a non-abstract method on the mapper itself - in case it is an abstract class and not an interface - define the mapping from Object to TicketDetails yourself:
TicketDetails asTicketDetails(Object details) {
return (TicketDetails) details;
}
The generated method for the conversion of SourceClassModel to TargetClassModel will then invoke that manually written method for converting the myTicket property.

How to serialize a field of a non-primitive type (your own class) in a Storm topology?

The following exception is thrown while I run my Storm project:
java.lang.RuntimeException: java.io.NotSerializableException: com.youtab.dataType.id.GUID
at backtype.storm.serialization.DefaultSerializationDelegate.serialize(DefaultSerializationDelegate.java:43)
at backtype.storm.utils.Utils.serialize(Utils.java:85)
at backtype.storm.topology.TopologyBuilder.createTopology(TopologyBuilder.java:111)
As part of my Storm project, I am trying to transmit an Object type Event from the first Spout to the first Bolt and then to use it.
Unfortunately, after implementing all needed changes and commits in my configuration variable - as described in the Storm documentations, it is still failing to deserialize one private field of type "GUID" which is one field from my own private class Event.
I have created the following serializing class:
public class GUIDSerializer extends Serializer<GUID> {
#Override
public void write(Kryo kryo, Output output, GUID guid) {
output.write(guid.toString().getBytes());
}
#Override
public GUID read(Kryo kryo, Input input, Class<GUID> aClass) {
return GUID.of(input.readString());
}
}
And I registered the serialize as needed:
Config conf = new Config();
conf.registerSerialization(GUID.class, GUIDSerializer.class);
All classes used as data type for attributes/fields must implement Java's Serializable interface. In your case, this applies to your Event class as well as all used members of Event like GUID. Of course, this applied recursively, ie, if GUID contains custom types, those must implement Serializable, too.
Providing a custom Kryo serializer is actually not required. Storm can use Java's default serializer. For performance reasons however, it is highly recommended to register custom types. In most case, it is sufficient to simple register the user type classes via
conf.registerSerialization(MyUserType.class);
In your case
conf.registerSerialization(Event.class);
conf.registerSerialization(GUID.class);
Registering a class allows Storm to use a more efficient (general) Kryo serializer instead of Java's default serializer.
If this general Kryo serializer is still not efficient enough, you can provide an own Kryo serializer (as you mentioned in your question). However, the class must still implement Java's Serializable interface!
I do not know the Serializer class, but judging from the exception, you need to make your GUID class implement the Interface java.io.Serializable like:
public class GUID implements Serializable {
//...
When in doubt, please post your current code for GUID.

How to use Custom type for #PathParam?

I want to use non spring bean class object as parameter for jersey web service class method. But it is giving missing dependency error at build time.
My code is:
#Component
#Path("/abcd")
public class ActorServiceEndpoint {
#POST
#Path("/test/{nonspringBean}")
#Produces(MediaType.APPLICATION_XML)
public void addActor(#PathParam("nonspringBean") MyNonSpringBeanClass nonspringBean){
}
}
The thing is path parameters come in String form. As per the specification, if we want the have a custom type be injected as a #PathParam, the custom class, should have one of three things:
A public static valueOf(String param) that returns the type
A public static fromString(String param) that returns the type
Or a public constructor that accepts a String
Another option implement a ParamConverter. You can see an example here.
If you don't own the class (it's a third-party class that you can't change) then your only option is to use the ParamConverter/ParamConverterProvider pair.
In either of these cases you'll want to construct the instance accordingly by parsing the String either in the constructor or in one of the above mentioned methods. After doing this, the custom type can be made a method parameter with the annotation.
The same holds true for other params, such as #FormParam, #HeaderParam, #QueryParam, etc.
It would help if you gave a bit more details of the error you're getting, but I see two problems with your code snippet:
The correct Spring annotation is #PathVariable, #PathParam is probably from another package. This doesn't apply as I guess you're using JAX-RS, not Spring annotations.
I'm not sure what converters are applied to path variables, but in any case it would need to have one for MyNonSpringBeanClass. I would take a String parameter and then instantiate MyNonSpringBeanClass myself in the function body.

JAXB "nor any of its super class is known to this context" avoid #XmlSeeAlso

Explanation & Workaround
Currently I am using JAX-RS and letting JAXB bindings automatically handle converting the data to XML and JSON for me in a JEE6 project. Everything is working absolutely fantastically until I try to create a generic response object to wrap all of my information in.
When I attempt to use my generic response class com.eln00b.Wrapper (which contains a private Object result attribute within it) I get:
javax.xml.bind.MarshalException - with linked exception: [com.sun.istack.SAXException2: class com.eln00b.CustomObject nor any of its super class is known to this context. javax.xml.bind.JAXBException: class com.eln00b.CustomObject nor any of its super class is known to this context.]
So I add to com.eln00b.Wrapper:
#XmlSeeAlso ({com.eln00b.CustomObject})
public class Wrapper {
}
Everything works fine.
The Problem
I want this to be extremely generic. I do not want t constantly add classes to the #XmlSeeAlso annotation on the com.eln00b.Wrapper class. How do I have the system automatically locate all of my classes for the JAXB context?
Even if it's a hack where I use something like Reflections to load the data, that's fine. I'm just not sure how to get the context to load all of that data without the #XmlSeeAlso annotation. With the large amount of annotations I will be creating it will just simply not work.
How It Worked Manually
It worked manually just by adding the data like so doing manual conversions. However, I do not want to use manual XML/JSON creation unless I absolutely need to (I don't want to deal with content negotiation or anything like that).
Sample:
JAXBContext.newInstance(new Class[] {Wrapper.class, CustomObject.class});
So here is what the essence of the custom resolver looks like:
#Provider
#Produces ({MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON})
public class JaxbContextResolver implements ContextResolver<JAXBContext> {
#Override
public JAXBContext getContext(Class<?> type) {
// load appropriate context data
Class[] bindTypes = ...
// create
try {
return JAXBContext.newInstance(bindTypes);
} catch (JAXBException e) {
// todo: this can be handled better but works for the example
throw new RuntimeException(e);
}
}
}
Now, the processing for "load appropriate context data" is pretty simple. By basically mimicking #XmlSeeAlso using runtime data:
Create a custom something (annotation, processing method, whatever) that marks a particular field/method as "contextual"
Load the field/method data pulling the data types out
Make sure you do not load duplicates and check for infinite recursion possibilities
Now, I used some caching to help make things more efficient for myself. I also created a slightly more complex setup for my root object where it actually kept track of the class data on its own and made it pretty speedy. I also created an alternative that marked classes as "contextual" that I used package inspection to load via annotations and just automatically add to the context but I have not checked efficiency on that yet. I have some ideas for a 3rd implementation, but I want to get more benchmarking completed.

Categories

Resources