SonarQube Rules Conflict - sonarqube

SonarQube reported 'Make "ids" transient or serializable' for this line of code:
private final List<String> ids;
So I changed it to:
private final ArrayList<String> ids;
and made sure that my public interface (the constructor in this case) still used just an interface:
public MyClass(List<String> ids) {
this.ids = (ids == null) ? new ArrayList<>() : new ArrayList<>(ids);
}
This got rid of the first SonarQube warning, but now it gives:
The type of the "ids" object should be an interface such as "List" rather than the implementation "ArrayList".
I don't want to turn off all rules for using interfaces rather than concrete classes, but only for cases like this.

You don't say what version of the Java plugin you're using, but it's likely pre-3.4; that rule was relaxed in v3.4 to ignore private fields.

Related

What 'final' keyword next to the field stands for?

In a legacy code, I'm working with, I found the following thing:
#Autowired
final lateinit var controller: CustomController
what does this final keyword mean here?
In a Kotlin documentation I found a short description about final keyword that is blocking overriding of the methods in open classes but no information about fields. Also - the class within which I found the line is not open
A final property or a method in Kotlin prevents overriding of the field / method. That being said, Kotlin by default considers a property or a method/function to be final unless specified by the keyword open. In your case, the final keyword is redundant.
Here's a small demo test case to illustrate the same.
open class Parent {
open val someValue = 0
final val otherValue = 13 // redundant modifier 'final' warning in Android Studio
}
class Child : Parent() {
override val someValue = 5
// override val otherValue = 19 // compile error
}
There is an interesting problem called Fragile Base Class in OOP and why some languages like Kotlin prefer final by default.
What you have there is a property, not a field.
It looks just like a field, as it would in Java; but in Kotlin, it actually defines a public getter method, a public setter method, and a private backing field*.
So the final modifier applies to the accessor methods, preventing those from being overridden in a subclass.  (As you say, the backing field itself can't be overridden anyway.)
As Siddharth says, final is the default in Kotlin, so you usually wouldn't need to specify it, though there are a few situations in which it would be needed — e.g. if it were already overriding something, or you were using the all-open or kotlin-spring compiler plug-ins.  (The use of #Autowired suggests that this is a Spring module, which probably explains why final is needed here.)  In any case, your IDE would probably indicate where it's not needed, e.g. by showing it greyed-out.
(* Only the getter is necessary; the setter isn't generated for a val, and the backing field isn't generated if you override the accessor(s) and they don't refer to it.)

How can you use different operators with QueryDSL Web?

I am using QueryDSL in my Spring Boot project and planning to use Spring's web support for it (current query dsl web docs). The problem is, I can't find anything about using different operators. How can I define a not equals or matches regex operation? At first glance, all it does is translating your ?fieldname=value format GET request to a predefined operation you set in your repository. Can I extend it in a way to allow multiple operations for the same field?
Example.:
Currently I can get a QueryDsl Predicate by passing URL paramters, like ?user.company.id=1:
#Controller
class UserController {
#Autowired UserRepository repository;
#RequestMapping(value = "/", method = RequestMethod.GET)
Page<User> getUsers(#QuerydslPredicate(root = User.class) Predicate predicate,
Pageable pageable) {
return repository.findAll(predicate, pageable);
}
}
But as the documentation I linked states, I can only define a single operation for a certain field. What If I want the Users, where the user.lastName starts with something and still keep the possibility to query for exact match? (?lastName=Xyz,contains and ?lastName=Xyz,equals maybe)
The QuerydslBinderCustomizer defines operations per field basis, but you can only define how to handle that particular field, there is no possibility to add multiple operations.
Maybe I cannot do this with QueryDSL, but then generally in Spring boot how do you apply filters to a search query?
I'm doing something like that. Although I'm facing some limitations when I try to do more complicated actions. What I've done in some steps:
Create a new interface MyBinderCustomizer<T extends EntityPath<?>> that extends QuerydslBinderCustomizer<QUser> (note the Q of User, you want QueryDSL autogenerated class instead of your entity).
Implement customize method. For example:
#Override
public default void customize(QuerydslBindings bindings, T root) {
bindings.bind(String.class).all(MyBinderCustomizer::applyStringComparison);
}
static BooleanExpression applyStringComparison(Path<String> path, Collection<? extends String> strings) {
BooleanExpression result = null;
for (String s : strings) {
try {
final String[] parts = s.split(",");
final String operator = parts[0];
final String value = parts.length > 1 ? parts[1] : null;
final Method method = Arrays.stream(path.getClass().getMethods())
.filter(m -> operator.equals(m.getName()))
.filter(m -> BooleanExpression.class.equals(m.getReturnType()))
.filter(m -> m.getParameterTypes().length == (value == null ? 0 : 1))
.filter(m -> value == null || m.getParameterTypes()[0].equals(String.class) || m.getParameterTypes()[0].equals(Object.class))
.findFirst().get();
final BooleanExpression be;
if (value == null) {
be = (BooleanExpression) method.invoke(path);
} else {
be = (BooleanExpression) method.invoke(path, value);
}
result = result == null ? be : result.and(be);
} catch (Throwable t) {
throw new RuntimeException(t);
}
}
return result;
}
Note you should change value/operator order, so you can call no-value operators like isNull.
Your repository must extend MyBinderCustomizer<QUser> (note Q again).
This will let you use these operations:
public BooleanExpression StringExpression.like(java.lang.String)
public BooleanExpression StringExpression.notLike(java.lang.String)
public BooleanExpression StringExpression.notEqualsIgnoreCase(java.lang.String)
public BooleanExpression StringExpression.containsIgnoreCase(java.lang.String)
public BooleanExpression StringExpression.likeIgnoreCase(java.lang.String)
public BooleanExpression StringExpression.startsWithIgnoreCase(java.lang.String)
public BooleanExpression StringExpression.endsWithIgnoreCase(java.lang.String)
public BooleanExpression StringExpression.equalsIgnoreCase(java.lang.String)
public BooleanExpression StringExpression.startsWith(java.lang.String)
public BooleanExpression StringExpression.endsWith(java.lang.String)
public BooleanExpression StringExpression.matches(java.lang.String)
public BooleanExpression StringExpression.contains(java.lang.String)
public BooleanExpression StringExpression.isEmpty()
public BooleanExpression StringExpression.isNotEmpty()
public BooleanExpression SimpleExpression.isNull()
public BooleanExpression SimpleExpression.isNotNull()
public BooleanExpression SimpleExpression.ne(java.lang.Object)
public BooleanExpression SimpleExpression.eq(java.lang.Object)
The Spring Data QueryDSL Value Operators library extends Spring Data QueryDSL web support with operators for not only String fields, but also Number and Enum fields. It requires some special configuration to make it work for the non-String fields, as explained here:
Value operators work seemlessly on String based properties/fields. However these operators do not work well with non-string values like Number or Enum since by default QuerydslPredicateArgumentResolver that resolves annotation QuerydslPredicate, which is used to annotate search handling method on RESTful method (aka RestController methods), performs strong-typing as per the guiding design principle of Querydsl, i.e. it attempts to convert the value(s) received from HTTP request to exact type defined in corresponding Q-Classes. This works well without value operators and is inline with Querydsl promise of allowing type-safe queries however hinders the path for value-operators to do their trick.
The library provides two methods to make operators work for non-String fields:
a Filter that extracts operators from query parameters, so the query parameters can still be converted to their corresponding type (using strong-typing)
replacing the ConversionService in the QuerydslPredicateArgumentResolver so all query parameters are treated as String (loosing the strong-typing)
Both approaches are well documented, along with their use case and disadvantages.
I am currently evaluating approach 1, as this fits our use case, but I need to extend it to accommodate DateTime fields and some custom operators as well.
https://bitbucket.org/gt_tech/spring-data-querydsl-value-operators/src/master/
Documentation here says:
QuerydslPredicateArgumentResolver uses ConversionService for type-conversion. Since conversion of String to Enum or String to Integer is core to Spring's dependency injection, it isn't advisable to change those default built-in converters (never do it). The library provides an experimental combination of a BeanPostProcessor and a ServletFilter that can be explicitly configured in target application's context to disable the strong type-conversion attempted by QuerydslPredicateArgumentResolver.
So to achieve this you need to add this to the application context:
/**
* Note the use of delegate ConversionService which comes handy for types like
* java.util.Date for handling powerful searches natively with Spring data.
* #param factory QuerydslBindingsFactory instance
* #param conversionServiceDelegate delegate ConversionService
* #return
*/
#Bean
public QuerydslPredicateArgumentResolverBeanPostProcessor querydslPredicateArgumentResolverBeanPostProcessor(
QuerydslBindingsFactory factory, DefaultFormattingConversionService conversionServiceDelegate) {
return new QuerydslPredicateArgumentResolverBeanPostProcessor(factory, conversionServiceDelegate);
}
Let me know if someone has success implementing this experimental functionality.
You can try using an additional lightweight library that helps to query fields using different operators LIKE, IN, EQ, NE etc. All you have to do is to add the dependency:
<dependency>
<groupId>io.github.apulbere</groupId>
<artifactId>rsql-querydsl</artifactId>
<version>1.0</version>
</dependency>
Define a model that will represent your search criteria:
#Setter
#Getter
public class UserCriteria {
StringCriteria lastName = StringCriteria.empty();
}
Use it as query parameter in your controller and build a dynamic predicate based on it:
#GetMapping("/users")
List<User> search(UserCriteria criteria, Pageable page) {
var predicate = criteria.lastName.match(QUser.user.lastName);
return userRepository.findAll(predicate, page);
}
Finally, make requests:
LIKE example: /users?lastName.like=Xyz
Equals examples: /users?lastName=Xyz or /users?lastName.eq=Xyz
There are other operators too.

Multi-Column Search with Spring JPA Specifications

I want to create a multi field search in a Spring-Boot back-end. How to do this with a Specification<T> ?
Environment
Springboot
Hibernate
Gradle
Intellij
The UI in the front end is a Jquery Datatable. Each column allows a single string search term to be applied. The search terms across more than one column is joined by a and.
I have the filters coming from the front end already getting populated into a Java object.
Step 1
Extend JPA Specification executor
public interface SomeRepository extends JpaRepository<Some, Long>, PagingAndSortingRepository<Some, Long>, JpaSpecificationExecutor {
Step2
Create a new class SomeSpec
This is where I am lost as to what the code looks like it and how it works.
Do I need a method for each column?
What is Root and what is Criteria Builder?
What else is required?
I am rather new at JPA so while I don't need anyone to write the code for me a detailed explanation would be good.
UPDATE
It appears QueryDSL is the easier and better way to approach this. I am using Gradle. Do I need to change my build.gradle from this ?
If you don't want to use QueryDSL, you'll have to write your own specifications. First of all, you need to extend your repository from JpaSpecificationExecutor like you did. Make sure to add the generic though (JpaSpecificationExecutor<Some>).
After that you'll have to create three specifications (one for each column), in the Spring docs they define these specifications as static methods in a class. Basically, creating a specification means that you'll have to subclass Specification<Some>, which has only one method to implement, toPredicate(Root<Some>, CriteriaQuery<?>, CriteriaBuilder).
If you're using Java 8, you can use lambdas to create an anonymous inner class, eg.:
public class SomeSpecs {
public static Specification<Some> withAddress(String address) {
return (root, query, builder) -> {
// ...
};
}
}
For the actual implementation, you can use Root to get to a specific node, eg. root.get("address"). The CriteriaBuilder on the other hand is to define the where clause, eg. builder.equal(..., ...).
In your case you want something like this:
public class SomeSpecs {
public static Specification<Some> withAddress(String address) {
return (root, query, builder) -> builder.equal(root.get("address"), address);
}
}
Or alternatively if you want to use a LIKE query, you could use:
public class SomeSpecs {
public static Specification<Some> withAddress(String address) {
return (root, query, builder) -> builder.like(root.get("address"), "%" + address + "%");
}
}
Now you have to repeat this for the other fields you want to filter on. After that you'll have to use all specifications together (using and(), or(), ...). Then you can use the repository.findAll(Specification) method to query based on that specification, for example:
public List<Some> getSome(String address, String name, Date date) {
return repository.findAll(where(withAddress(address))
.and(withName(name))
.and(withDate(date));
}
You can use static imports to import withAddress(), withName() and withDate() to make it easier to read. The where() method can also be statically imported (comes from Specification.where()).
Be aware though that the method above may have to be tweaked since you don't want to filter on the address field if it's null. You could do this by returning null, for example:
public List<Some> getSome(String address, String name, Date date) {
return repository.findAll(where(address == null ? null : withAddress(address))
.and(name == null ? null : withName(name))
.and(date == null ? null : withDate(date));
}
You could consider using Spring Data's support for QueryDSL as you would get quite a lot without having to write very much code i.e. you would not actually have to write the specifictions.
See here for an overview:
https://spring.io/blog/2011/04/26/advanced-spring-data-jpa-specifications-and-querydsl/
Although this approach is really convenient (you don’t even have to
write a single line of implementation code to get the queries
executed) it has two drawbacks: first, the number of query methods
might grow for larger applications because of - and that’s the second
point - the queries define a fixed set of criterias. To avoid these
two drawbacks, wouldn’t it be cool if you could come up with a set of
atomic predicates that you could combine dynamically to build your
query?
So essentially your repository becomes:
public interface SomeRepository extends JpaRepository<Some, Long>,
PagingAndSortingRepository<Some, Long>, QueryDslPredicateExecutor<Some>{
}
You can also get request parameters automatically bound to a predicate in your Controller:
See here:
https://spring.io/blog/2015/09/04/what-s-new-in-spring-data-release-gosling#querydsl-web-support
SO your Controller would look like:
#Controller
class SomeController {
private final SomeRepository repository;
#RequestMapping(value = "/", method = RequestMethod.GET)
String index(Model model,
#QuerydslPredicate(root = Some.class) Predicate predicate,
Pageable pageable) {
model.addAttribute("data", repository.findAll(predicate, pageable));
return "index";
}
}
So with the above in place it is simply a Case of enabling QueryDSL on your project and the UI should now be able to filter, sort and page data by various combinations of criteria.

OData (Olingo) "inhibit" endpoint

My question is about what is best way to inhibit an endpoint that is automatically provided by Olingo?
I am playing with a simple app based on Spring boot and using Apache Olingo.On short, this is my servlet registration:
#Configuration
public class CxfServletUtil{
#Bean
public ServletRegistrationBean getODataServletRegistrationBean() {
ServletRegistrationBean odataServletRegistrationBean = new ServletRegistrationBean(new CXFNonSpringJaxrsServlet(), "/user.svc/*");
Map<String, String> initParameters = new HashMap<String, String>();
initParameters.put("javax.ws.rs.Application", "org.apache.olingo.odata2.core.rest.app.ODataApplication");
initParameters.put("org.apache.olingo.odata2.service.factory", "com.olingotest.core.CustomODataJPAServiceFactory");
odataServletRegistrationBean.setInitParameters(initParameters);
return odataServletRegistrationBean;
} ...
where my ODataJPAServiceFactory is
#Component
public class CustomODataJPAServiceFactory extends ODataJPAServiceFactory implements ApplicationContextAware {
private static ApplicationContext context;
private static final String PERSISTENCE_UNIT_NAME = "myPersistenceUnit";
private static final String ENTITY_MANAGER_FACTORY_ID = "entityManagerFactory";
#Override
public ODataJPAContext initializeODataJPAContext()
throws ODataJPARuntimeException {
ODataJPAContext oDataJPAContext = this.getODataJPAContext();
try {
EntityManagerFactory emf = (EntityManagerFactory) context.getBean(ENTITY_MANAGER_FACTORY_ID);
oDataJPAContext.setEntityManagerFactory(emf);
oDataJPAContext.setPersistenceUnitName(PERSISTENCE_UNIT_NAME);
return oDataJPAContext;
} catch (Exception e) {
throw new RuntimeException(e);
}
}
...
My entity is quite simple ...
#Entity
public class User {
#Id
private String id;
#Basic
private String firstName;
#Basic
private String lastName;
....
Olingo is doing its job perfectly and it helps me with the generation of all the endpoints around CRUD operations for my entity.
My question is : how can I "inhibit" some of them? Let's say for example that I don't want to enable the delete my entity.
I could try to use a Filter - but this seems a bit harsh. Are there any other, better ways to solve my problem?
Thanks for the help.
As you have said, you could use a filter, but then you are really coupled with the URI schema used by Olingo. Also, things will become complicated when you have multiple, related entity sets (because you could navigate from one to the other, making the URIs more complex).
There are two things that you can do, depending on what you want to achieve:
If you want to have a fined grained control on what operations are allowed or not, you can create a wrapper for the ODataSingleProcesor and throw ODataExceptions where you want to disallow an operation. You can either always throw exceptions (i.e. completely disabling an operation type) or you can use the URI info parameters to obtain the target entity set and decide if you should throw an exception or call the standard single processor. I have used this approach to create a read-only OData service here (basically, I just created a ODAtaSingleProcessor which delegates some calls to the standard one + overridden a method in the service factory to wrap the standard single processor in my wrapper).
If you want to completely un-expose / ignore a given entity or some properties, then you can use a JPA-EDM mapping model end exclude the desired components. You can find an example of such a mapping here: github. The mapping model is just an XML file which maps the JPA entities / properties to EDM entity type / properties. In order for olingo to pick it up, you can pass the name of the file to the setJPAEdmMappingModel method of the ODataJPAContext in your initialize method.

How does Spring Data JPA work internally

I was going through Spring Data JPA Tutorial.
I am confused on how does this framework work internally.
Let me state specific scenario
There was specific code
/**
* Custom finder
*/
public List<Location> getLocationByStateName(String name) {
#SuppressWarnings("unchecked")
List<Location> locs = entityManager
.createQuery("select l from Location l where l.state like :state")
.setParameter("state", name + "%").getResultList(); // note
return locs;
}
This was simply replaced by following interface
#Repository
public interface LocationJPARepository extends JpaRepository<Location, Long> {
List<Location> findByStateLike(String stateName);
}
And corresponding test case worked fine
#Test
public void testFindWithLike() throws Exception {
List<Location> locs = locationRepository.getLocationByStateName("New");
assertEquals(4, locs.size());
}
New test case
#Test
public void testFindWithLike() throws Exception {
List<Location> locs = locationJPARepository.findByStateLike("New");
assertEquals(4, locs.size());
}
My question
How does framework know if i am looking for exact match using = or partial match using SQL like operator (it cant be method name ?)
if it somehow decide I am looking for partial match then still there are sub options ... like name% or %name or %name% …
Also how it decides case is important in like ? ( i can have case-insensitive by using SQL like with toUpper() i.e. by comparing everything in upper case )
(added ques) is there a way i can check the EXACT SQL in log some where ??
Hope i was able to explain my question properly. Let me know if i need to add in more clarity.
I recommend to take a look at Query Creation section of the reference guide. It explains the rules pretty clearly.
For instance when you want to find User by first name and ignore case, you would use method name like findByFirstnameIgnoreCase which would translate into condition like UPPER(x.firstame) = UPPER(?1).
By default when you have findByProperty method, the match is exact, so if you want to have LIKE functionality you would use method name findByFirstnameLike which would in turn translate into condition where x.firstname like ?1.
You can combine these keywords, but it can get a little crazy. Personally I prefer using #Query annotation for more complicated queries to avoid super long repository method names.

Resources