Mapstruct - mapper object needs valuemapping of an object field - mapstruct

I have an object A which I am trying to map to B. Now this A has an enum named field1 with some values. I want to map them using #ValueMappings to someother enum value in B. Below is my code till now:
#Mapping(source = "field1", target = "field1", nullValuePropertyMappingStrategy = IGNORE)
#Mapping(source = "field2", target = "field2", nullValuePropertyMappingStrategy = IGNORE)
#ValueMappings({
#ValueMapping(source = "field1.some1", target = "diff1"),
#ValueMapping(source = "field1.some2", target = "diff1"),
#ValueMapping(source = "field1.some3", target = "diff1"),
#ValueMapping(source = "field1.some4", target = "diff2"),
})
B map(A a);
When I try to compile this, I get the error:
error: The following constants from the property "A.field1 field1" enum have no corresponding constant in the "B field1" enum and must be be mapped via adding additional mappings: diff1, diff2.

One way to solve this problem is to do something like this:
#Mapper(componentModel = "spring", uses = {SomeUtil.class}, unmappedTargetPolicy = ReportingPolicy.IGNORE)
public interface Mapper {
#Mapping(source = "field1", target = "field1", nullValuePropertyMappingStrategy = IGNORE)
#Mapping(source = "field2", target = "field2", nullValuePropertyMappingStrategy = IGNORE)
B map(A a);
}
And in SomeUtil.class:
#Mapper(componentModel = "spring")
public interface SomeUtil {
#ValueMappings({
#ValueMapping(source = "field1.some1", target = "diff1"),
#ValueMapping(source = "field1.some2", target = "diff1"),
#ValueMapping(source = "field1.some3", target = "diff1"),
#ValueMapping(source = "field1.some4", target = "diff2"),
})
b.field1 map(a.field1 field);
}

Related

Wrong PUT method gets triggered in Akka Http using scala

In my APIendpoint class, I have 2 PUT methods lets say updateA and UpdateB but when I'm trying to hit UpdateB using swagger it resolves to a UpdateA everytime. I dunno what I'm doing wrong because the code seems ok to me. Any help is appreciated.
#Api(value = "/connectroutes", produces = "application/json", consumes = "application/json",
authorizations = Array(new Authorization(value = "")))
#Produces(Array(MediaType.APPLICATION_JSON))
def routes: Route = {
pathPrefix("sampleroute") {
authenticateBasic(realm = "sample realm", authenticator) { authenticationResult =>
updateA ~
updateB
}
}
#PUT
#Path("{name}")
#Produces(Array(MediaType.APPLICATION_JSON))
#Operation(summary = "sample", description = "UPDATE A",
parameters = Array(new Parameter(name = "name", in = ParameterIn.PATH, description = "updateA name", required = true)),
requestBody = new RequestBody(content = Array(new Content(schema = new Schema(implementation = classOf[A]), mediaType = MediaType.APPLICATION_JSON))),
)
def updateA: Route = {
path(Segment) { name =>
put {
entity(as[A]) { a: A => {
complete(updateAMethod(name, a))
}
}
}
}
}
#PUT
#Path("updateb")
#Produces(Array(MediaType.APPLICATION_JSON))
#Authorization("basicAuth")
#Operation(summary = "Sample", description = "Update B",
requestBody = new RequestBody(content = Array(new Content(schema = new Schema(implementation = classOf[String]), mediaType = MediaType.APPLICATION_JSON))),
)
def updateB: Route = {
path("updateb" / Segment) { namespace =>
put {
entity(as[String]) { updatedval: String => {
complete(updatedVal))
}
}
}
}
}

How to assign the values for an HttpRequestMessage class?

I struggle with assigning values to an 'HttpRequestMessage' class.
My code is:
let requestMsg = new HttpRequestMessage()
requestMsg.RequestUri = new System.Uri("https://yh-finance.p.rapidapi.com/stock/v2/get-summary?symbol=BMW.DE&region=DE");;
When I assign the URL, I get the response:
val it : bool = false
I tried to assign a different Method but also got the same response.
> requestMsg.Method = HttpMethod.Post;;
val it : bool = false
requestMsg has this content:
> requestMsg;;
val it : HttpRequestMessage =
Method: GET, RequestUri: '<null>', Version: 1.1, Content: <null>, Headers:
{
}
{Content = null;
Headers = seq [];
Method = GET;
Options = seq [];
Properties = seq [];
RequestUri = null;
Version = 1.1;
VersionPolicy = RequestVersionOrLower;}
How can I modify the HttpRequestMessage object?
Assignment in F# is done with <-: https://learn.microsoft.com/en-us/dotnet/fsharp/language-reference/values/#mutable-variables
requestMsg.Method <- HttpMethod.Post

How to use DateTime in Expressions for LINQ to Entities?

I know how to build an Expression tree to query Entity Framework, eg.
string propertyName = "Name";
string keyword = "Methanol";
ParameterExpression parameter = Expression.Parameter(typeof(Chemical), "x");
MemberExpression me = Expression.Property(parameter, propertyName);
ConstantExpression constant = Expression.Constant(keyword, typeof(string));
BinaryExpression body = Expression.Equal(me, constant);
var isEqualExpressionTree = Expression.Lambda<Func<Chemical, bool>>(body, new[] { parameter });
Expression<Func<Chemical, bool>> funcExpression = (Expression<Func<Chemical, bool>>)isEqualExpressionTree;
using (var mLEntities = new myLab02Entities1())
{
var cl = mLEntities.Chemicals.AsQueryable().Where(funcExpression).ToList();
return cl;
}
"Name" is a field in the SQL-database and it should be checked for "Methanol". The Lambda that is build inside is:
{x => (x.Name == "Methanol")}. Now I want to test DateTime fields of the database, but only with the Date-portion. So my Lambda would be
{x => DbFunctions.TruncaateTime(x.EntryDate) == DbFunction.TruncateTime(testDate)}. This works as is, but how can I convert this to an Expression?
Thanks, Hucky
string propertyName = "EntryDate";
DateTime testDate = DateTime.Now;
ParameterExpression parameter = Expression.Parameter(typeof(Chemical), "x");
MemberExpression me = Expression.Property(parameter, propertyName);
var ce = Expression.Convert(me, typeof(DateTime?));
MethodCallExpression mc = Expression.Call(null, typeof(DbFunctions).GetMethod("TruncateTime", new Type[] { typeof(DateTime?) }), ce);
ConstantExpression constant = Expression.Constant(testDate, typeof(DateTime?));
BinaryExpression body = Expression.Equal(mc, constant);
var isEqualExpressionTree = Expression.Lambda<Func<Chemical, bool>>(body, new[] { parameter });
Expression<Func<Chemical, bool>> funcExpression = (Expression<Func<Chemical, bool>>)isEqualExpressionTree;

Need more efficient way to convert Entities to DataTable

So, I have a method that converts entities into a DataTable. The only problem is it is very slow. I made sure to call .ToList() on the IQueryable to make it go ahead and load before processing the results into a DataTable. It takes hardly any time to load the 3000+ rows into memory. However, the real time slayer is in the following iteration in the method:
foreach (var index in imgLeaseIndexes)
{
DataRow dataRow = dataTable.NewRow();
dataRow["StateCode"] = index.StateCode;
dataRow["CountyCode"] = index.CountyCode;
dataRow["EntryNumber"] = index.EntryNumber;
dataRow["Volume"] = index.Volume;
dataRow["Page"] = index.Page;
dataRow["PageCount"] = index.ImgLocation.PageCount;
dataRow["CreateDate"] = index.ImgLocation.CreateDate;
dataTable.Rows.Add(dataRow);
}
And here is the complete method, for what it's worth:
private DataTable buildImgLeaseIndexDataTable(List<ImgLeaseIndex> imgLeaseIndexes)
{
var dataTable = new DataTable();
var dataColumns = new List<DataColumn>();
var tdiReportProperties =
new List<string>() { "StateCode", "CountyCode", "EntryNumber", "Volume", "Page", "PageCount", "CreateDate" };
Type imgLeaseIndexType = imgLeaseIndexes.FirstOrDefault().GetType();
PropertyInfo[] imgLeaseIndexPropertyInfo = imgLeaseIndexType.GetProperties();
dataColumns.AddRange(
(from propertyInfo in imgLeaseIndexPropertyInfo
where tdiReportProperties.Contains(propertyInfo.Name)
select new DataColumn()
{
ColumnName = propertyInfo.Name,
DataType = (propertyInfo.PropertyType.IsGenericType &&
propertyInfo.PropertyType.GetGenericTypeDefinition() == typeof(Nullable<>)) ?
propertyInfo.PropertyType.GetGenericArguments()[0] : propertyInfo.PropertyType
})
.ToList());
Type imgLocationType = imgLeaseIndexes.FirstOrDefault().ImgLocation.GetType();
PropertyInfo[] imgLocationPropertyInfo = imgLocationType.GetProperties();
dataColumns.AddRange(
(from propertyInfo in imgLocationPropertyInfo
where tdiReportProperties.Contains(propertyInfo.Name)
select new DataColumn()
{
ColumnName = propertyInfo.Name,
DataType = (propertyInfo.PropertyType.IsGenericType &&
propertyInfo.PropertyType.GetGenericTypeDefinition() == typeof(Nullable<>)) ?
propertyInfo.PropertyType.GetGenericArguments()[0] : propertyInfo.PropertyType
})
.ToList());
dataTable.Columns.AddRange(dataColumns.ToArray());
foreach (var index in imgLeaseIndexes)
{
DataRow dataRow = dataTable.NewRow();
dataRow["StateCode"] = index.StateCode;
dataRow["CountyCode"] = index.CountyCode;
dataRow["EntryNumber"] = index.EntryNumber;
dataRow["Volume"] = index.Volume;
dataRow["Page"] = index.Page;
dataRow["PageCount"] = index.ImgLocation.PageCount;
dataRow["CreateDate"] = index.ImgLocation.CreateDate;
dataTable.Rows.Add(dataRow);
}
return dataTable;
}
Does anyone have ideas on how I can make this more efficient and why it is so slow as is?
UPDATE:
I removed the reflection and explicitly set the data columns at compile time per the feedback I've received so far, but it is still really slow. This is what the updated code looks like:
private DataTable buildImgLeaseIndexDataTable(List<ImgLeaseIndex> imgLeaseIndexes)
{
var dataTable = new DataTable();
var stateCodeDataColumn = new DataColumn();
stateCodeDataColumn.ColumnName = "StateCode";
stateCodeDataColumn.Caption = "State Code";
stateCodeDataColumn.DataType = typeof(Int16);
dataTable.Columns.Add(stateCodeDataColumn);
var countyCodeDataColumn = new DataColumn();
countyCodeDataColumn.ColumnName = "CountyCode";
countyCodeDataColumn.Caption = "County Code";
countyCodeDataColumn.DataType = typeof(Int16);
dataTable.Columns.Add(countyCodeDataColumn);
var entryNumberDataColumn = new DataColumn();
entryNumberDataColumn.ColumnName = "EntryNumber";
entryNumberDataColumn.Caption = "Entry Number";
entryNumberDataColumn.DataType = typeof(string);
dataTable.Columns.Add(entryNumberDataColumn);
var volumeDataColumn = new DataColumn();
volumeDataColumn.ColumnName = "Volume";
volumeDataColumn.DataType = typeof(string);
dataTable.Columns.Add(volumeDataColumn);
var pageDataColumn = new DataColumn();
pageDataColumn.ColumnName = "Page";
pageDataColumn.DataType = typeof(string);
dataTable.Columns.Add(pageDataColumn);
var pageCountDataColumn = new DataColumn();
pageCountDataColumn.ColumnName = "PageCount";
pageCountDataColumn.Caption = "Page Count";
pageCountDataColumn.DataType = typeof(string);
dataTable.Columns.Add(pageCountDataColumn);
var createDateDataColumn = new DataColumn();
createDateDataColumn.ColumnName = "CreateDate";
createDateDataColumn.Caption = "Create Date";
createDateDataColumn.DataType = typeof(DateTime);
dataTable.Columns.Add(createDateDataColumn);
foreach (var index in imgLeaseIndexes)
{
DataRow dataRow = dataTable.NewRow();
dataRow["StateCode"] = index.StateCode;
dataRow["CountyCode"] = index.CountyCode;
dataRow["EntryNumber"] = index.EntryNumber;
dataRow["Volume"] = index.Volume;
dataRow["Page"] = index.Page;
dataRow["PageCount"] = index.ImgLocation.PageCount;
dataRow["CreateDate"] = index.ImgLocation.CreateDate;
dataTable.Rows.Add(dataRow);
}
return dataTable;
}
Any ideas on what else might be causing this?
UPDATE 2:
So it looks like other people have had this problem - specific to creating and setting the DataRows. My co-worker came across this:
The DataRow value setter is slow!
I'm going to try some of the stuff suggested in the link.
As Thiago mentioned in the comments the problem is the use of reflection.
The reflection part is where you are using PropertyInfo. You are getting the structure of the data types at runtime. But these are known at compile time.

How to write JPQL query using multiple members of same collection?

I have a noticication entity that has OneToMany relationship with its parameters, which is a list of NotificationParamEntity objects.
The code for both classes looks like:
// Notification Entity
#Entity
#Table (name = "NOTIFICATIONS")
public class NotificationEntity {
......
#OneToMany (mappedBy = "notification")
private List<NotificationParamEntity> params;
......
}
// Notification Parameter Entity
#Entity
#Table (name = "NOTIFICATIONS_PARAM")
public class NotificationParamEntity {
......
#Column (name = "KEY", length = 40, nullable = false)
#Enumerated (EnumType.STRING)
private NotificationParameterEnum key;
#Column (name = "VALUE", length = 4000, nullable = false)
private String value;
#ManyToOne
#JoinColumn (name = "NOTIFICATION_ID", nullable = false)
private NotificationEntity notification;
......
}
Now I can use the query below to get the notification that has a parameter named "P1" and with a value "V1":
SELECT DISTINCT anEntity FROM NotificationEntity anEntity, IN
(anEntity.params) p WHERE p.key = "P1" AND p.value = 'V1'
But when I want to find out the notification that has two specified parameters(P1=V1 and P2=V2), my query below failed to find anything:
SELECT DISTINCT anEntity FROM NotificationEntity anEntity, IN
(anEntity.params) p WHERE p.key = "P1" AND p.value = 'V1' AND p.key = "P2" AND p.value = "V2"
I can understand why it doesn't work: there is no parameter that can have two different keys, so the query return nothing.
But how to make this work? Assume I have a notification entity that has two parameters, one is named P1 and value is V1, the other one is P2 and the value is V2, how can I find this notification entity with JPQL query?
Try something like this:
SELECT n FROM NotificationEntity n WHERE EXISTS
(SELECT p FROM NotificationParamEntity p WHERE p.key = 'P1' AND p.value = 'V1'
AND p.notificationEntity = n)
AND EXISTS
(SELECT p2 FROM NotificationParamEntity p2 WHERE p2.key = 'P2' AND p2.value = 'V2'
AND p2.notificationEntity = n)
Note that it requires a reference from NotificationParamEntity to NotificationEntity (I don't see that column in the snippet of your code, but you should have it, a #ManyToOne).