Clojure - How to Declare a Collection or Vector of a Record - data-structures

How Can I define a Record Collection or a Vector of Records?
I have this snippet code:
(defrecord Transaction [a, b, c])
I want define a Transaction collection called LastTransactions to implement a function like this:
(defn can-authorize
"Validate Authorization by Transaction"
[^Transaction transaction, ^LastTransactions lastTransactions]
(... business logic)
)
First Question, is that the right way to do that?
Second, How can i declare that structure?

Clojure's type hints don't offer any type validation - you can use Clojure Spec or Plumatic Schema for that. They only serve for the compiler to prevent reflection when Java methods are called on the parameters. For that purpose, you don't need to type hint a vector since Clojure's core functions for collections (first, conj, etc.) by design don't require reflection on standard collections.
However, if you need, you can type-hint the elements that you extract from the lastTransaction sequence, for example:
(defn can-authorize
"Validate Authorization by Transaction"
[^Transaction transaction, lastTransactions]
...
(for [^Transaction t lastTransactions]
(...do-something-with t))

Type-hints are used to avoid reflection. They are not used to statically type function or constructor args.
Just use basic ^java.util.List type-hint instead of ^LastTransactions. In this case, any use of wrong lastTransactions in the body of the function will fail with ClassCastException. However, it won't check the type of elements in that list. To do so, use type hinting everytime you work with elements of lastTransactions.
Example 1 with type hinting:
(defn can-authorize
[^Transaction transaction, ^java.util.List lastTransactions]
(.size lastTransactions)
)
In this case, decompiled java code will look like:
// Decompiling class: user$can_authorize
import clojure.lang.*;
import java.util.*;
public final class user$can_authorize extends AFunction
{
public static Object invokeStatic(final Object transaction, Object lastTransactions) {
final Object o = lastTransactions;
lastTransactions = null;
return ((List)o).size();
}
public Object invoke(final Object transaction, final Object lastTransactions) {
return invokeStatic(transaction, lastTransactions);
}
}
Example 2 without type hinting:
(defn can-authorize [^String transaction, lastTransactions]
(.size lastTransactions))
decompiled to:
// Decompiling class: user$can_authorize
import clojure.lang.*;
public final class user$can_authorize extends AFunction
{
public static Object invokeStatic(final Object transaction, Object lastTransactions) {
final Object target = lastTransactions;
lastTransactions = null;
return Reflector.invokeNoArgInstanceMember(target, "size", false);
}
public Object invoke(final Object transaction, final Object lastTransactions) {
return invokeStatic(transaction, lastTransactions);
}
}
Compare the resulted return statements:
with type hinting
return ((List)o).size();
without type hinting
return Reflector.invokeNoArgInstanceMember(target, "size", false);
PS: code decompiled by using clj-java-decompiler

Related

can i convert any lambda expression into method reference

I wonder if can i convert any lambda expression into method reference
for example:
if there is a lambda that execute method with 2 parameters (one of them is from outside)
.map( t -> removeFilesIfNessasary( externalObj, t ) )
can this also converted into method reference?
thanks
Well you could create a class, sort of like this:
class Remover {
private final Object externalObj;
public Remover(Object externalObj){
this.externalObj = externalObj;
}
public removeIf(int t){
removeFilesIfNessasary( externalObj, t);
}
}
and then declare this and use it:
Remover remover = new Remover(externalObj);
.map(remover::remove);
But seriously, this looks really weird; there has to be a compelling reason for you to do this (I can't think of one).

Combining functions and consumers with double-column notation

I often use the double-colon notation for brevity.
I am writing the following method that takes a short list of entities, validates them, and saves back to database.
#Override#Transactional
public void bulkValidate(Collection<Entity> transactions)
{
Consumer<Entity> validator = entityValidator::validate;
validator = validator.andThen(getDao()::update);
if (transactions != null)
transactions.forEach(validator);
}
I'd like to know if there is a shorthand syntax avoiding to instantiate the validator variable
Following syntax is invalid ("The target type of this expression must be a functional interface")
transactions.forEach((entityValidator::validate).andThen(getDao()::update));
You could do that, but you would need to cast explicitly...
transactions.forEach(((Consumer<Entity>)(entityValidator::validate))
.andThen(getDao()::update));
The thing is that a method reference like this entityValidator::validate does not have a type, it's a poly expression and it depends on the context.
You could also define a method to combine these Consumers:
#SafeVarargs
private static <T> Consumer<T> combine(Consumer<T>... consumers) {
return Arrays.stream(consumers).reduce(s -> {}, Consumer::andThen);
}
And use it:
transactions.forEach(combine(entityValidator::validate, getDao()::update))

Dropwizard deserializing generic list from JerseyClient

I wanted to implement a generic class to use for caching results from a REST API in a local MongoDB-instance. For this to work, I need to deserialize a collection I get from JerseyClient:
Response response = this.source.request().get();
List<T> list = response.readEntity( new GenericType<List<T>>() {} );
// ... do stuff with the list
Let's say I'm using this piece of code in a context of T relating to a class Foo. The really weird thing is, after the readEntity call, list is not a List<Foo>, instead is a List<LinkedHashMap>. How is that even possible, when I've clearly declared the Generic T to be Foo?
What do I have to do to get a proper List<T>, i.e. List<Foo> instead?
Note: If I remove the generic, and use
List<Foo> list = response.readEntity( new GenericType<List<Foo>>() {} );
directly instead, it works fine, but I really need that generic to be there!
Java's most popular excuse for Generics: Type Erasure
If you can pass your class type as Class<T> clazz, then you can use this:
GenericType<List<T>> genericType = new GenericType<>(new ParameterizedType() {
public Type[] getActualTypeArguments() {
return new Type[]{clazz};
}
public Type getRawType() {
return List.class;
}
public Type getOwnerType() {
return null;
}
});
response.readEntity(genericType);
You can use
import sun.reflect.generics.reflectiveObjects.ParameterizedTypeImpl;
import javax.ws.rs.core.GenericType;
GenericType<List<T>> genericType = new GenericType<>(
ParameterizedTypeImpl.make( List.class, new Type[]{classType}, null));

Dynamic Repository With Dynamic Methods

Inspired by this post dynamic-repositories-in-lightspeed I am trying to build my own like this.
I have a abstract GenericRepository like this. I have omitted most of the code for simplicity (Its just normal Add/Update/Filtering methods).
public abstract class GenericRepository<TEntity, TContext> :
DynamicObject,
IDataRepository<TEntity>
where TEntity : class, new()
where TContext : DbContext, new()
{
protected TContext context;
protected DbSet<TEntity> DbSet;
}
As you can see, my abstract GenericRepository extends from DynamicObject to support dynamic repositories.
I also have a abstract UnitOfWork implementation which generated a repository for a given entity at runtime like this. Again, base classes and other details are irrelevant for the question, but I'm happy to provide them if you require.
public abstract class UnitOfWorkBase<TContext> : IUnitOfWork
where TContext : DbContext, new()
{
public abstract IDataRepository<T> Repository<T>()
where T : class, IIdentifiableEntity, new();
// Code
}
Following class implements abstract method of the above class.
public class MyUnitOfWorkBase : UnitOfWorkBase<MyDataContext>
{
public override IDataRepository<T> Repository<T>()
{
if (Repositories == null)
Repositories = new Hashtable();
var type = typeof(T).Name;
if (!Repositories.ContainsKey(type))
{
var repositoryType = typeof(GenericRepositoryImpl<,>);
var genericType = repositoryType.MakeGenericType(typeof(T), typeof(InTeleBillContext));
var repositoryInstance = Activator.CreateInstance(genericType);
Repositories.Add(type, repositoryInstance);
}
return (IDataRepository<T>)Repositories[type];
}
}
Now, whenever I want to create a dynamic repository for basic CRUD functions, I can do it like this.
var uow = new MyUnitOfWorkBase();
var settingsRepo = uow.Repository<Settings>();
var settingsList = settingsRepo.Get().ToList();
Now, What I want to do is something like this.
dynamic settingsRepo = uow.Repository<Settings>();
var result = settingsRepo.FindSettingsByCustomerNumber(774278L);
Here, FindSettingsByCustomerNumber() is a dynamic method. I resolve this method using this code.
public class GenericRepositoryImpl<TEntity, TContext> :
GenericRepository<TEntity, TContext>
where TEntity : class, IIdentifiableEntity, new()
where TContext : DbContext, new()
{
public override bool TryInvokeMember(InvokeMemberBinder binder,
object[] args, out object result)
{
// Crude parsing for simplicity
if (binder.Name.StartsWith("Find"))
{
int byIndex = binder.Name.IndexOf("By");
if (byIndex >= 0)
{
string collectionName = binder.Name.Substring(4, byIndex - 4);
string[] attributes = binder.Name.Substring(byIndex + 2)
.Split(new[] { "And" }, StringSplitOptions.None);
var items = DbSet.ToList();
Func<TEntity, bool> predicate = entity => entity.GetType().GetProperty(attributes[0]).GetValue(entity).Equals(args[0]);
result = items.Where(predicate).ToList();
return true;
}
}
return base.TryInvokeMember(binder, args, out result);
}
}
This is the problem I am having.
using this line var items = DbSet.ToList(); works well, but if I were to query a large table with 1000's of data, then performance issues occur.
If I directly try to use the IQueryble interface and call it like this
Func predicate = entity => entity.GetType().GetProperty(attributes[0]).GetValue(entity).Equals(args[0]);
result = DbSet.Where(predicate).ToList();
It gives me an error saying there is no method GetProperty() in LINQ to Entities.
Is it possible to make it work using LINQ to Entities?
You need to know that LINQ-to-Entities needs to convert your expression (given by the predicate) into a SQL query. entity is replaced by the database column. Additionally LINQ2Entities supports various expressions (e.g. EqualExpression, etc.). However it cannot support the whole .NET Framework. Especially: what should GetType() on a database column return?
Therefore you need to use the Expresson API to generate the predicate and use only expressions supported by LINQ2Entities. For example: Use a MemberAccess expression for accessing a property (LINQ2Entities is able to map that to an SQL query).
Hint: we are doing predicate generation for Entity Framework and had to overcome some additional problems which we could solve using the library LinqKit.
If you do not know about the .NET Expression API yet, you need to gather skills in that area before you can resume your dynamic repository idea.
BTW: I don't think that it is a very good idea to have this kind of automatic calls. They are not refactoring safe (i.e. what if you rename the DB column? All your method calls run into problems, and it is not detectable by the compiler).
I would use it only to generate predicates for Where() clauses from Filter-like DTO types.
Unusual pattern - dynamic methods on a repository patterns.But that is another topic.
Dynamic invocation of the repository you have.
So now you need to understand Linq to Entities a little more.
Linq to Entities language reference what you can do with linq to Entities.
Given the expression tree has to be converted in to DB instructions,
it isnt surprising there are restrictions.
In case you are interested The EF provider specs and links to samples
So given you want to Dynamic EF, you have a few options.
I concentrate on dynamic wheres, but you can apply to other EF methods.
Check out
Dynamic Linq on codeplex
which allows things like
public virtual IQueryable<TPoco> DynamicWhere(string predicate, params object[] values) {
return Context.Set<TPoco>().Where(predicate, values);
}
This Where is an IQueryable extension that accepts strings...
Samples of using this string based predicate parser
LinqKit or even PM> Install-Package LinqKit
Linqkit takes dynamic EF to the next level,
Offers amazing features like
public IQueryable<TPoco> AsExpandable() {
return Context.Set<TPoco>().AsExpandable();
}
which allows you build AND and ORs progressively.
Expression trees
Expression Building API is the most powerful tool to support you here .
Learning the API is hard. using the tool harder.
eg Dealing with concatenation very hard. BUT if you can understand the API and how expressions work.
It is possible.
Here is a SIMPLE example. (imagine something complex)
public static Expression<Func<TPoco, bool>> GetContainsPredicate<TPoco>(string propertyName,
string containsValue)
{
// (tpoco t) => t.propertyName.Contains(value ) is built
var parameterExp = Expression.Parameter(typeof(TPoco), #"t");
var propertyExp = Expression.Property(parameterExp, propertyName);
MethodInfo method = typeof(string).GetMethod(#"Contains", new[] { typeof(string) });
var someValue = Expression.Constant(containsValue, typeof(string));
var containsMethodExp = Expression.Call(propertyExp, method, someValue);
return Expression.Lambda<Func<TPoco, bool>>(containsMethodExp, parameterExp);
}

NHibernate: Using a LINQ expression with IQueryOver

I'm trying to use the IQueryOver interface of a NHibernate session object together with a LINQ expression as a criteria for selecting records in a static class. The LINQ expressions are defined in a mapping class as Expression<Func<T, object>> to get a value for an object T:
public void SearchParameter(Expression<Func<T, object>>)
These parameters get added by extending the mapping class:
public MyMapping : FindMap<MyNHibernateMappedObject>
{
public MyMapping()
{
this.SearchParameter(x => x.SomeColumn);
}
}
My Find class defines static methods for getting the previous and next record of the same type on the time axis. Each search parameter has to be identical in both records.
The Find class gets the search parameters from the mapping configuration and compiles the expressions with .Compile(). So I have the GetQueryWithSearchParameters method:
private static Func<T, object> searchParameter;
...
public static IQueryOver<T, T> GetQueryWithSearchParameters(ISession session, T current)
{
var query = session.QueryOver<T>()
.Where(x => searchParameter(x) == searchParameter(current));
return query;
}
However when building the query, I get the following exception:
System.InvalidOperationException: variable 'x' of type MyNHibernateMappedObject' referenced from scope '', but it is not defined
I don't know exactly what is going on here, but I suspect that x is not available in the delegate somehow. What am I doing wrong here?
session.QueryOver().Where(...) takes an expression, so it's going to try evaluate your expression and translate it to a query - ie. it will try to convert searchParameter(x) == searchParameter(current) into a SQL query, which it won't know how to do.
To get this to work you will need to construct the expression in code (not using a lambda expression). However I think that this is going to be a painful exercise and I think you will find it much easier to build a Criterion and add that to the QueryOver.

Resources