ModelMapper and tree structures - tree-structure

I've got a tree-like structure of entities that I'm trying to map to DTOs using ModelMapper. The trick is that I'm trying to break the graph after the first parent.
Following is a example of what I'm trying to do. I've got a Category entity which has a name and a parent Category. I want my DTO to have a link to it's parent but don't want the latter to have it's own parent (so that I don't get the whole hierarchy)
The trouble is that ModelMapper does not map my DTO's parent because it's of a different type; I declared it as being a DTO rather that a CategoryDTO in order to break the recursion.
If I DO declare my parent as a CategoryDTO, the mapping works fine but I will get all of my parents and grand parents (which I do not want).
Anybody knows how I could fix this?
import java.util.UUID;
import org.junit.Assert;
import org.junit.Test;
import org.modelmapper.ModelMapper;
public class CategoryTest {
public static class Category {
private String uid = UUID.randomUUID().toString();
private String name;
private Category parent;
public Category () {}
public Category(String name, Category parent) {
this.name = name;
this.parent = parent;
}
public String getUid() {return uid;}
public void setUid(String uid) {this.uid = uid;}
public String getName() {return name;}
public void setName(String name) {this.name = name;}
public Category getParent() {return parent;}
public void setParent(Category parent) {this.parent = parent;}
}
public static class DTO {
private String uid;
private String name;
public String getUid() {return uid;}
public void setUid(String uid) {this.uid = uid;}
public String getName() {return name;}
public void setName(String name) {this.name = name;}
}
public static class CategoryDTO extends DTO {
private DTO parent;
public DTO getParent() {return parent;}
public void setParent(DTO parent) {this.parent = parent;}
}
#Test
public void simpleTest() {
Category dto = new Category("Test1",null);
CategoryDTO entity = new ModelMapper().map(dto, CategoryDTO.class);
Assert.assertEquals("Test1", entity.getName());
Assert.assertEquals(dto.getUid(), entity.getUid());
}
#Test
public void withParentTest() {
Category dto = new Category("child",new Category("root", null));
CategoryDTO entity = new ModelMapper().map(dto, CategoryDTO.class);
Assert.assertEquals("child", entity.getName());
Assert.assertEquals(dto.getUid(), entity.getUid());
Assert.assertNotNull(entity.getParent());
}
}

I've managed to solve my problem by customizing my ModelMapper with a Converter. My ModelMapper is now fetched by calling this method:
private ModelMapper getModelMapper() {
ModelMapper map = new ModelMapper();
map.addConverter(new AbstractConverter<Category, AbstractDTO>() {
#Override
protected AbstractDTO convert(Category source) {
if (source == null) return null;
AbstractDTO dto = new AbstractDTO();
dto.setUid(source.getUid());
dto.setName(source.getName());
return dto;
}
});
return map;
}

Related

Method does not exist or incorrect signature : void

I'm getting the below error while saving the test class. Can anyone help on this please?
Error :
Method does not exist or incorrect signature: void exceptionLogFromFlow(List<CS_ExceptionLoggerFlowTest.WrapperClass>) from the type CS_ExceptionLoggerFlow
Test Class:
#istest
Public class CS_ExceptionLoggerFlowTest {
#istest
static void SingleExceptionMethod() {
WrapperClass wlu=new wrapperClass();
wlu.apexClass ='CS_ExceptionLoggerFlow';
Wlu.methodName='createExceptionLog';
Wlu.exceptionMessage='message';
Wlu.exceptionDated=System.today();
Wlu.isAPIFailure = false;
Wlu.userName='userName';
list<WrapperClass> wpl= new list<WrapperClass>();
wpl.add(wlu);
Test.startTest();
CS_ExceptionLoggerFlow.exceptionLogFromFlow(wpl);
Test.stopTest();
}
public class WrapperClass {
public String apexClass;
public String methodName;
public String exceptionMessage;
public DateTime exceptionDated;
public Boolean isAPIFailure;
public String userName;
}
}
Main Class:
public class CS_ExceptionLoggerFlow {
#InvocableMethod(label='Exception Log From Flow')
public static void exceptionLogFromFlow(List<Params> inputVars) {
String serializedstring=JSON.serialize(inputVars);
String returnString = serializedstring.substring(1,serializedstring.length()-1);
createExceptionLog(returnString);
}
#future
public static void createExceptionLog(String futureParams){
List<ExceptionLogger__c> logList = new List<ExceptionLogger__c>();
WrapperClass value = (WrapperClass) JSON.deserialize(futureParams, WrapperClass.class);
List<WrapperClass> wpl= new List<WrapperClass>();
wpl.add(value);
for(WrapperClass vlu:wpl){
ExceptionLogger__c log = new ExceptionLogger__c();
log.Apex_Class__c = vlu.apexClass;
log.Method_Name__c = vlu.methodName;
log.Description__c = vlu.exceptionMessage;
log.Exception_Dated__c = vlu.exceptionDated;
log.API_Failure__c = vlu.isAPIFailure;
log.User_Name__c = vlu.userName;
logList.add(log);
}
insert logList;
}
public class Params {
#InvocableVariable public String apexClass;
#InvocableVariable public String methodName;
#InvocableVariable public String exceptionMessage;
#InvocableVariable public DateTime exceptionDated;
#InvocableVariable public Boolean isAPIFailure;
#InvocableVariable public String userName;
}
public class WrapperClass {
public String apexClass;
public String methodName;
public String exceptionMessage;
public DateTime exceptionDated;
public Boolean isAPIFailure;
public String userName;
}
}

Spring-batch ItemProcessor data in the form of a list to model

I'm using a custom itemReader to read data from an external rest API, and it's working great. However, the problem arises when processing the data with ItemProcessor into my model class. Unfortunately, the API response is an object with an array nested inside of it, which means I have to use a list referencing another class to store the data inside of it.
picture of API response
StockDTO data class:
public class StockDTO {
// We will change the field data types later when we process the data into our model.
private String from;
private String to;
private List<ProductDTO> products;
// Getters and Setters allow RestTemplate to set the data from the external rest API.
public String getFrom() {
return from;
}
public void setFrom(String from) {
this.from = from;
}
public String getTo() {
return to;
}
public void setTo(String to) {
this.to = to;
}
public List<ProductDTO> getProducts() {
return products;
}
public void setProducts(List<ProductDTO> products) {
this.products = products;
}
}
ProductDTO data class (list data):
public class ProductDTO {
// We will change the field data types later when we process the data into our model.
private String sku;
private String name;
private String startDate;
// Getters and Setters allow RestTemplate to set the data from the external rest API.
public String getSku() {
return sku;
}
public void setSku(String sku) {
this.sku = sku;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getStartDate() {
return startDate;
}
public void setStartDate(String startDate) {
this.startDate = startDate;
}
}
model class:
#Entity
public class Stock {
#Id
private long id;
private int item_from;
private int item_to;
private long sku;
private String name;
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public int getItem_from() {
return item_from;
}
public void setItem_from(int item_from) {
this.item_from = item_from;
}
public int getItem_to() {
return item_to;
}
public void setItem_to(int item_to) {
this.item_to = item_to;
}
public long getSku() {
return sku;
}
public void setSku(long sku) {
this.sku = sku;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
ItemProcessor<StockDTO, Stock>
public class StockDataProcessor implements ItemProcessor<StockDTO, Stock> {
#Override
public Stock process(StockDTO stockDTO) throws Exception {
Stock stock = new Stock();
stock.setItem_from(Integer.parseInt(stockDTO.getFrom()));
stock.setItem_to(Integer.parseInt(stockDTO.getTo()));
// I'm only able to get the first index sku, name from the list:
stock.setSku(Long.parseLong(stockDTO.getProducts().get(0).getSku()));
stock.setName(stockDTO.getProducts().get(0).getName());
return stock;
}
}
Should I create another model class called Product so that I can create ItemProcessor<ProductDTO, Product> or can I get all the list items from ItemProcessor<StockDTO, Stock> without creating another processor? Thank you.
You could create another model class called Product and modify the Stock class to include a List and modify your ItemProcessor to populate the list of Product in the Stock class.
Alternatively, you could make your ItemProcessor return a List instead of just a single Stock. Your ItemWriter would then need to process a List<List>.

Akka Rest Server Jackson ObjectReader and ObjectWriter Initialization

I am using jackson ObjectReader and ObjectWriter object for serialization and deserialization in Akka Rest Server.
I am getting byteString in the request and deserialize it to object. Below is the scala code for it.
val a = objectReader.readValue[java.util.List[Base[Long]]](request.toArray)
Base class is an abstract class and I can have multiple implementation of it
#JsonTypeInfo(use = JsonTypeInfo.Id.NAME,
property = "impl")
#JsonSubTypes({
#JsonSubTypes.Type(value = A.class, name = "A")
})
public abstract class Base<T> implements Serializable {
private String impl;
private ResponseStatus status;
public String getImpl() {
return impl;
}
public void setImpl(String impl) {
this.impl = impl;
}
public void setStatus(ResponseStatus status) {
this.status = status;
}
public ResponseStatus getStatus() {
return status;
}
public static class ResponseStatus implements Serializable {
private ReturnCode code;
private String msg;
public void setCode(ReturnCode code) {
this.code = code;
}
public void setMsg(String msg) {
this.msg = msg;
}
public ReturnCode getCode() {
return code;
}
public String getMsg() {
return msg;
}
}
}
How ever I have observed that first call for readValue and writeValueAsBytes takes long.
I tried initializing it. But still it is not improving in Akka Execution Context. Anyone know the solution of it? Please help.

JAX-WS Endpoint bean creation fails with ServiceConstructionException

I am trying to publish a webservice with spring-boot
Here is how I have set it up.
I have an interface that has some methods say
#WebService
public interface FirstInterface
{
#WebMethod
void method1(#WebParam(name = "id") String id);
void method2(#WebParam(name = "id2") String id);
}
I have another interface that has some more methods
and it extends FirstInterface
#WebService
public interface SecondInterface extends FirstInterface
{
#WebMethod
void method3(#WebParam(name = "id") String id);
void method4(#WebParam(name = "id2") String id);
}
Now I have an implementation class that implements SecondInterface
and has an endpointInterface referring to my SecondInterface something like this:
#Service
#WebService(endpointInterface = "com.somepackage.SecondInterface")
public class CallBackServicesImpl implements SecondInterface
{
#Override
//override all four methods here
}
Now I have a configuration class that is publishing these services
#Configuration
public class WebServiceConfig
{
#Bean
public Endpoint endpoint() {
EndpointImpl endpoint = new EndpointImpl(springBus(), serviceImpl());
endpoint.publish(SERVICE_NAME_PATH);
return endpoint;
}
}
Problem: The webservice gets published with this setup with endpointinterface pointing to FirstInterface but only two methods will be available for use.
Now I all want four methods to be available for the client to use, so I point endpointinterface to SecodInterface and it start throwing exception saying Error creating bean with name 'endpoint',org.apache.cxf.service.factory.ServiceConstructionException
Am I missing something basic here? How can I achieve this behavior?
Remove the #WebService annotation on impl class
Here is the working copy
FirstInterface.java
#WebService
public interface FirstInterface {
#WebMethod
void method1(#WebParam(name = "id") String id);
#WebMethod
void method2(#WebParam(name = "id2") String id);
}
SecondInterface.java
#WebService
public interface SecondInterface extends FirstInterface {
#WebMethod
void method3(#WebParam(name = "id") String id);
#WebMethod
void method4(#WebParam(name = "id2") String id);
}
Impl class
#Service
public class KPImpl implements SecondInterface {
public static final Logger LOG = LoggerFactory.getLogger(KPImpl.class);
#Override
public void method3(String id) {
LOG.info("Method3 {}", id);
}
#Override
public void method4(String id) {
LOG.info("Method4 {}", id);
}
#Override
public void method1(String id) {
LOG.info("Method1 {}", id);
}
#Override
public void method2(String id) {
LOG.info("Method2 {}", id);
}
}
Finally configuration file
#Configuration
public class WsConfiguration {
#Bean
public Server getJaxWsServer(SpringBus bus, KPImpl impl) {
final JaxWsServerFactoryBean serverFctry = new JaxWsServerFactoryBean();
serverFctry.setAddress("/kp");
serverFctry.setServiceBean(impl);
serverFctry.setServiceClass(KPImpl.class);
serverFctry.getFeatures().add(new LoggingFeature());
return serverFctry.create();
}
}

How to raise an event in a test that uses Moq?

Here is part of code implementation in parent class:
handler.FooUpdateDelegate += FooUpdate(OnFooUpdate);
protected abstract void OnFooUpdate(ref IBoo boo, string s);
I have in test method mocked handler:
Mock<IHandler> mHandler = mockFactory.Create<IHandler>();
This...
mHandler.Raise(x => x.FooUpdateDelegate += null, boo, s);
...is not working. It says:
System.ArgumentException : Could not locate event for attach or detach method Void set_FooUpdateDelegate(FooUpdate).
I want to raise OnFooUpdate so it triggers the code to be tested in child class.
Question: How can I raise delegate (not common event handler) with Moq?
If I missed the point completely, please enligten me.
It looks like you are trying to raise a delegate rather than an event. Is this so?
Is your code along the lines of this?
public delegate void FooUpdateDelegate(ref int first, string second);
public class MyClass {
public FooUpdateDelegate FooUpdateDelegate { get; set; }
}
public class MyWrapperClass {
public MyWrapperClass(MyClass myclass) {
myclass.FooUpdateDelegate += HandleFooUpdate;
}
public string Output { get; private set; }
private void HandleFooUpdate(ref int i, string s) {
Output = s;
}
}
If so, then you can directly invoke the myClass FooUpdateDelegate like so
[TestMethod]
public void MockingNonStandardDelegate() {
var mockMyClass = new Mock<MyClass>();
var wrapper = new MyWrapperClass(mockMyClass.Object);
int z = 19;
mockMyClass.Object.FooUpdateDelegate(ref z, "ABC");
Assert.AreEqual("ABC", wrapper.Output);
}
EDIT: Adding version using interface
public interface IMyClass
{
FooUpdateDelegate FooUpdateDelegate { get; set; }
}
public class MyClass : IMyClass {
public FooUpdateDelegate FooUpdateDelegate { get; set; }
}
public class MyWrapperClass {
public MyWrapperClass(IMyClass myclass) {
myclass.FooUpdateDelegate += HandleFooUpdate;
}
public string Output { get; private set; }
private void HandleFooUpdate(ref int i, string s) {
Output = s;
}
}
[TestMethod]
public void MockingNonStandardDelegate()
{
var mockMyClass = new Mock<IMyClass>();
// Test fails with a Null Reference exception if we do not set up
// the delegate property.
// Can also use
// mockMyClass.SetupProperty(m => m.FooUpdateDelegate);
mockMyClass.SetupAllProperties();
var wrapper = new MyWrapperClass(mockMyClass.Object);
int z = 19;
mockMyClass.Object.FooUpdateDelegate(ref z, "ABC");
Assert.AreEqual("ABC", wrapper.Output);
}