How to automate Methods mapping between two java classes? - spring

I have a legacy springMvc project and i want to refactor all the controllers to return ResponseEntity object rather then returning Model object which is returned by default.
I am looking for a way to map functions in Map class to ResponseEntity class .
I have seen people recommend to use Regular expression as a solution to refactor all the methods.
I need to know your opinion about implementing Regex as solution in terms of advantages / drawbacks for using regex in this scenario.
In addition it would be helpful if you can suggest other solutions.
please take a look at the attached code for more details.
return Model object to the view
#GetMapping("/getData")
public String getData(Model model) {
model.addAttribute("message", "springMvc");
return "viewPage";
}
return ResponseEntity object as a json format
#GetMapping("/getData")
public ResponseEntity<Map<String,String>> getData() {
Map<String,String> map = new HashMap<>();
map.put("message", "springMvc");
return new ResponseEntity.Ok().body(map);
}

In case this problem is faced by someone in the future i would like to share that I have found a convenient way to do the refactoring of the code by using AST (Abstract Syntax Tree) which gives you a lot more control over the code comparing to using Regex.
you can check the library repository :
https://github.com/javaparser/javaparser
Note that AST is used by IDEs and Static analysis tools such as SonarQube

Regex cannot be used in your context. There are certainly too many special cases to change, it is not just a question of changing a string. JavaParser is a good candidate.

Related

Alternative to "JdbcTemplate" on migration from "Spring-boot" to "Quarkus"

I'm new to Quarkus and I'm analysing the migration viability of a quite complex "Spring Boot" application.
One of the biggest challenges we have is regarding database access, which is performed with tons of native queries using "JdbcTemplate" like the example below:
return getJdbcTemplate().query( sql, rs -> {
Map< String, String > result = new HashMap<>();
while ( rs.next() ) {
result.put( rs.getString( "COLUMN_1" ), rs.getString( "COLUMN_2" ) );
}
return result;
} );
Sometimes the result is cast to a basic class (like "String.class"), but the absolute majority of cases the result is generated by a "ResultSetExtractor".
After some research I found indications that Panache accepts native query execution (as described here) and, following this post, I found this one with a very nice alternative using "entityManager.createNativeQuery()".
For the sake of simplicity (and my sanity), I've decided to use the "entityManager.createNativeQuery()" approach, converting the implemented "ResultSetExtractor" into "ResultTranformers", given that this won't demand, among other things, the "entitization" of some POJOs that are used on data retrieval by now.
The main objective at the end of this compatibility change is to have an application that can be executed on "Spring-boot" and "Quarkus" (at least regarding the persistence layer).
One question I have is regarding the "entityManager" declaration below:
#PersistenceContext
private EntityManager entityManager;
Considering that we will use, at this first moment, the "quarkus-spring-di" compatibility extension (which means the class that holds the "entityManager" is annotated with "#Repository" and not with "#ApplicationScoped"), the "entityManager" will be initialized?
And, considering all that was presented here, do you guys have any suggestions or warnings about the decided course of action?
Thanks and best regards!

In spring data elasticsearch, how can I project or add a calculated field on all results?

I am using spring-data-elasticsearch (latest version) along with a docker instance of elasticsearch (latest version), and I want to calculate a field on all results that are returned from my repository after a query. I do not want this information in the repository, because it is sometimes query dependent, and sometimes environment dependent. For example, if we perform a query, I want to generate a URL that includes the query terms as query parameters in the URL that I want to enrich the result with. There are some other cases, too. I have tried creating a spring data custom reading converter that accepts the whole document object. I can see that it is recognized when the application starts, but it is never invoked. How can I either project a field with a custom value, or enrich the returned documents with a contextually calculated value?
I first thought about AfterConvertCallback as well like Chin commented, but in a callback you have no context of the query that was run to get the entity, so you cannot use things like query terms to build something.
I would add the property - let's name it url of type String here - to the entity and mark it with the org.springframework.data.annotation.Transient annotation to prevent it from being stored.
Then in the method where you do the search, either using ElasticsearchOperations or a repository, postprocess the returned entites (code not tested, just written down here):
SearchHits<Entity> searchHits = repository.findByFoo(String fooValue);
searchHits.getSearchHits().forEach(searchHit -> {
searchHit.getContent().setUrl(someValueDerivedFromEnvironemtAndQuery);
});
After that proceed using the SearchHits.
I like a hybrid approach of combining the answers from both #ChinHuang and #PJMeisch. Both answers have their applicability, depending on the context or situation. I like Chin Huang's suggestion for instance-based information, where you would need things like configuration values. I also agree that PJ Meisch is correct in his concern that this does not give you access to the immediate query, so I like his idea of intercepting/mapping the values when the data is being returned from the data store. I appreciate the great information from both people, because this combination of both approaches is a solution that I am happy with.
I prefer to use a repository interface wherever possible, because many people incorrectly mix business logic into their repositories. If I want custom implementation, then I am forced to really think about it, because I have to create an "Impl" class to achieve it. This is not the gravest of errors, but I always accompany a repository with a business service that is responsible for any data grooming, or any programmatic action that is not strictly retrieval, or persistence, of data.
Here is the part of my module configuration where I create the custom AfterConvertCallback. I set the base URL in the onAfterConvert method:
#Bean
AfterConvertCallback<BookInfo> bookInfoAfterConvertCallback() {
return new BookInfoAfterConvertCallback(documentUrl);
}
static class BookInfoAfterConvertCallback implements AfterConvertCallback<BookInfo> {
private final String documentUrl;
public BookInfoAfterConvertCallback(String documentUrl) {
this.documentUrl = documentUrl;
}
#Override
public BookInfo onAfterConvert(final BookInfo entity, final Document document, final IndexCoordinates indexCoordinates) {
entity.setUrl(String.format("%s?id=%d", documentUrl, entity.getId()));
return entity;
}
}
In the data service that invokes the repository query, I wrote a pair of functions that creates the query param portion of the URL so that I can append it in any applicable method that uses the auto-wired repository instance:
/**
* Given a term, encode it so that it can be used as a query parameter in a URL
*/
private static final Function<String, String> encodeTerm = term -> {
try {
return URLEncoder.encode(term, StandardCharsets.UTF_8.name());
} catch (UnsupportedEncodingException e) {
log.warn("Could not encode search term for document URL", e);
return null;
}
};
/**
* Given a list of search terms, transform them into encoded URL query parameters and append
* them to the given URL.
*/
private static final BiFunction<List<String>, String, String> addEncodedUrlQueryParams = (searchTerms, url) ->
searchTerms.stream()
.map(term -> String.format("term=%s", encodeTerm.apply(term)))
.filter(Objects::nonNull)
.collect(Collectors.joining("&", url + "&", ""));
This absolutely can all be done in a repository instance, or in its enclosing service. But, when you want to intercept all data that is retrieved, and do something with it that is not specific to the query, then the callback is a great option because it does not incur the maintenance cost of needing to introduce it in every data layer method where it should apply. At query time, when you need to reference information that is only available in the query, it is clearly a matter of introducing this type of code into your data layer (service or repo) methods.
I am adding this as an answer because, even though I didn't realize it at the time that I posted my question, this is two concerns that are separate enough to warrant both approaches. I do not want to claim credit for this answer, so I will not select it as the answer unless you both comment on this, and tell me that you want me to do that.

When to use Encapsulate Collection?

In the smell Data Class as Martin Fowler described in Refactoring, he suggests if I have a collection field in my class I should encapsulate it.
The pattern Encapsulate Collection(208) says we should add following methods:
get_unmodified_collection
add_item
remove_item
and remove these:
get_collection
set_collection
To make sure any changes on this collection need go through the class.
Should I refactor every class which has a collection field with this pattern? Or it depends on some other reasons like frequency of usage?
I use C++ in my project now.
Any suggestion would be helpful. Thanks.
These are well formulated questions and my answer is:
Should I refactor every class which has a collection field with this
pattern?
No, you should not refactor every class which has a collection field. Every fundamentalism is a way to hell. Use common sense and do not make your design too good, just good enough.
Or it depends on some other reasons like frequency of usage?
The second question comes from a common mistake. The reason why we refactor or use design pattern is not primarily the frequency of use. We do it to make the code more clear, more maintainable, more expandable, more understandable, sometimes (but not always!) more effective. Everything which adds to these goals is good. Everything which does not, is bad.
You might have expected a yes/no answer, but such one is not possible here. As said, use your common sense and measure your solution from the above mentioned viewpoints.
I generally like the idea of encapsulating collections. Also encapsulating plain Strings into named business classes. I do it almost always when the classes are meaningful in the business domain.
I would always prefer
public class People {
private final Collection<Man> people;
... // useful methods
}
over the plain Collection<Man> when Man is a business class (a domain object). Or I would sometimes do it in this way:
public class People implements Collection<Man> {
private final Collection<Man> people;
... // delegate methods, such as
#Override
public int size() {
return people.size();
}
#Override
public Man get(int index) {
// Here might also be some manipulation with the returned data etc.
return people.get(index);
}
#Override
public boolean add(Man man) {
// Decoration - added some validation
if (/* man does not match some criteria */) {
return false;
}
return people.add(man);
}
... // useful methods
}
Or similarly I prefer
public class StreetAddress {
private final String value;
public String getTextValue() { return value; }
...
// later I may add more business logic, such as parsing the street address
// to street name and house number etc.
}
over just using plain String streetAddress - thus I keep the door opened to any future change of the underlying logic and to adding any useful methods.
However, I try not to overkill my design when it is not needed so I am as well as happy with plain collections and plain Strings when it is more suited.
I think it depends on the language you are developing with. Since there are already interfaces that do just that C# and Java for example. In C# we have ICollection, IEnumerable, IList. In Java Collection, List, etc.
If your language doesn't have an interface to refer to a collection regarless of their inner implementation and you require to have your own abstraction of that class, then it's probably a good idea to do so. And yes, you should not let the collection to be modified directly since that completely defeats the purpose.
It would really help if you tell us which language are you developing with. Granted, it is kind of a language-agnostic question, but people knowledgeable in that language might recommend you the best practices in it and if there's already a way to achieve what you need.
The motivation behind Encapsulate Collection is to reduce the coupling of the collection's owning class to its clients.
Every refactoring tries to improve maintainability of the code, so future changes are easier. In this case changing the collection class from vector to list for example, changes all the clients' uses of the class. If you encapsulate this with this refactoring you can change the collection without changes to clients. This follows on of SOLID principles, the dependency inversion principle: Depend upon Abstractions. Do not depend upon concretions.
You have to decide for your own code base, whether this is relevant for you, meaning that your code base is still being changed and has to be maintained (then yes, do it for every class) or not (then no, leave the code be).

Specify ASP.NET MVC 3 Routes symbolically

I really like the ASP.NET MVC 3 framework. Or at least, it sure is incomparably better than trying to fool with ASP.NET 3.5 or 4.0. However, I am just really confused about something. Why did they choose to specify routes with strings?
IOW, I am told to specify my routes like this (for instance):
... new { controller = "Products", action = "List", id = UrlParameter.Optional }
This route matches a ProductsController.List() method. Let's say I'm in a refactoring mood and I want to rename my ProductsController to InventoryController. After using my renaming tool of choice, I have open up Global.aspx and go through all my routes and change all these stupid strings to "Inventory". You might respond that I can do a find and replace... but come on! I feel like that is such a last-generation answer.
I love refactoring my code as I come to understand my domain better. I don't want to use stupid (I say stupid because they have no significance to the compiler) strings to refer to symbolic/semantic code constructs that correspond exactly to type and method names that are ultimately stored in a symbol table. What is the point? Why bother with types at all? Let's just go back to writing scripts using associative arrays and dictionaries to represent our domain model... it seems to me that the benefit of strong typing is greatly lessened when we mix it with string references.
Seriously, though, an option would be reflection. Would there be a performance hit for this? I suppose the MVC framework must be using reflection on that "Products" string to get my ProductsController, so... But also, you would have to remove the "Controller" portion of the type name, as follows:
= typeof(ProductsController).Name.Replace("Controller", string.Empty)
I could use the following helper function to make it a little DRYer:
public string GetControllerName(Type controller)
{
return controller.Name.Replace("Controller", string.Empty);
}
Benchmarking is in order, if this is the only way to avoid those strings... Still, this is stupid. I'm using reflection on a type to get a string that MVC is going to use in conjunction with reflection to get the type I originally had in the first place.
Is there some reason not take the next (logical?) step and have the controller and action properties expect Types and Delegates directly? Wouldn't this simply be cleaner and clearer? So far as I understand, a fundamental aspect of MVC is convention over configuration, but routing with those strings just seems to be a furtive form of configuration to me.
Is there another way around this? I am still new to MVC. I've read that we can replace these routing components. Does anyone know if it is possible to do what I'm talking about? And if it's not possible, well... am I alone here? Am I missing something? Some overriding reason why it is essential that these routes be set by dumb strings? If not, could this maybe be something to lobby for?
Am I alone in hating it when strings are used in this way? I still think C# needs something akin to Ruby's symbols and Lisp's keywords that our refactoring tools could take advantage of. Sort of like "string enumerations" where the enumeration value name is at the same time the value.
I understand that parts of this question are subjective, but I am also looking for the objective answer on whether it is possible to directly use types and delegates to specify these routing configurations.
Thank you,
Jeromeyers
Personally I never had problems with the way routes are defined because I always unit test them. So if I am in a refactoring mood, my unit tests always guarantee me that the routes will behave as I want.
Of course if you are still not satisfied with the way the ASP.NET MVC team designed the framework (don't hesitate to open a ticket and vote for improvement in future versions) you could always write a custom route:
public class IHateMagicStringsRoute<T> : Route where T : Controller
{
public IHateMagicStringsRoute(
string url,
Expression<Func<T, ActionResult>> expression
) : base(url, Parse(expression), new MvcRouteHandler())
{ }
private static RouteValueDictionary Parse(Expression<Func<T, ActionResult>> expression)
{
var mce = expression.Body as MethodCallExpression;
if (mce != null)
{
return new RouteValueDictionary(new
{
controller = typeof(T).Name.Replace("Controller", ""),
action = mce.Method.Name
});
}
return null;
}
}
and then instead of:
routes.MapRoute(
"Default",
"{controller}/{action}",
new { controller = "Home", action = "Index" }
);
you could:
routes.Add(
new IHateMagicStringsRoute<HomeController>(
"{controller}/{action}",
x => x.Index()
)
);
Now you can rename your controllers and actions as much as you like.

EF4, Lambda, Repository pattern and DTOs

I have a semi complicated question regarding Entity Framework4, Lambda expressions, and Data Transfer Objects (DTO).
So I have a small EF4 project, and following established OO principles, I have a DTO to provide a layer of abstraction between the data consumers (GUI) and the data model.
VideoDTO = DTO with getters/setters, used by the GUI
VideoEntity = Entity generated by EF4
My question revolves around the use of the DTO by the GUI (and not having the GUI use the Entity at all), combined with a need to pass a lambda to the data layer. My data layer is a basic repository pattern with Add. Change, Delete, Get, GetList, etc.
Trying to implement a Find method with a signature like so:
public IEnumerable<VideoDTO> Find(Expression<Func<VideoEntity, bool>> exp)
...
_dataModel.Videos.Where(exp).ToList<Video>()
---
My problem/concern is the "exp" needing to be of type VideoEntity instead of VideoDTO. I want to preserve the separation of concerns so that the GUI does not know about the Entity objects. But if I try to pass in
Func<VideoDTO, bool>
I cannot then do a LINQ Where on that expression using the actual data model.
Is there a way to convert a Func<VideoDTO,bool> to a Func<VideoEntity, bool>
Ideally my method signature would accept Func<VideoDTO, bool> and that way the GUI would have no reference to the underlying data entity.
Is this clear enough? Thanks for your help
Thanks for the repliesto both of you.
I'll try the idea of defining the search criteria in an object and using that in the LINQ expression. Just starting out with both EF4 and L2S, using this as a learning project.
Thanks again!
In architectures like CQRS there isn't need for such a conversion at all cause read & write sides of app are separated.
But in Your case, You can't runaway from translation.
First of all - You should be more specific when defining repositories. Repository signature is thing You want to keep explicit instead of generic.
Common example to show this idea - can You tell what indexes You need in Your database when You look at Your repository signature (maybe looking at repository implementation, but certainly w/o looking at client code)? You can't. Cause it's too generic and client side can search by anything.
In Your example it's a bit better cause expression genericness is tied with dto instead of entity.
This is what I do (using NHibernate.Linq, but the idea remains)
public class Application{
public Project Project {get;set;}
}
public class ApplicationRepository{
public IEnumerable<Application> Search(SearchCriteria inp){
var c=Session.Linq<Application>();
var q=c.AsQueryable();
if(!string.IsNullOrEmpty(inp.Acronym))
q=q.Where(a=>a.Project.Acronym.Contains(inp.Acronym));
/*~20 lines of similar code snipped*/
return q.AsQueryable();
}
}
//used by client
public class SearchCriteria{
public string Acronym{get;set;}
/*some more fields that defines how we can search Applications*/
}
If You do want to keep Your expressions, one way would be to define dictionary manually like this:
var d=new Dictionary<Expression<Func<VideoDTO,object>>,
Expression<Func<VideoEntity,object>>{
{x=>x.DtoPropNumberOne,x=>x.EntityPropNumberOne} /*, {2}, {3}, etc.*/
};
And use it later:
//can You spot it?
//client does not know explicitly what expressions dictionary contains
_dataModel.Videos.Where(d[exp]).ToList<Video>();
//and I'm not 100% sure checking expression equality would actually work
If You don't want to write mapping dictionary manually, You will need some advanced techniques. One idea would be to translate dto expression to string and then back to entity expression. Here are some ideas (sorting related though) that might help. Expressions are quite complicated beasts.
Anyway - as I said, You should avoid this. Otherwise - You will produce really fragile code.
Perhaps your design goal is to prevent propagation of the data model entities to the client tier rather than to prevent a dependency between the presentation layer and data model. If viewed that way then there would be nothing wrong with the query being formed the way you state.
To go further you could expose the searchable fields from VideoEntity via an interface (IVideoEntityQueryFields) and use that as the type in the expression.
If you don't want to add an interface to your entities then the more complicated option is to use a VideoEntityQuery object and something that translates an Expression<Func<VideoEntityQuery,bool>> to an Expression<Func<VideoEntity,bool>>.

Resources