Does Intellij IDEA support #RooJpaRepository? - spring

IntelliJ 12.1.6 Ultimate, with following plugins enabled :
AspectJ Support
AspectJ Weaver
Spring Support
Spring Data
Spring AOP and #AspectJ
I have a Spring Roo project, which use Spring Data repository API. Following are snippet codes :
Repository class
package my.package;
#RooJpaRepository(domainType = Thing.class)
public interface ThingRepository {
}
Roo generated aspect file
privileged aspect ThingRepository_Roo_Jpa_Repository {
declare parents: ThingRepository extends JpaRepository<Thing, Long>;
declare parents: ThingRepository extends JpaSpecificationExecutor<Thing>;
declare #type: ThingRepository: #Repository;
}
Spring JPA config
<repositories base-package="my.package" />
But in xml file, IntelliJ told me
So whenever I use method like find/save in IntelliJ, it will be marked as "Cannot resolve method"
However, both IntelliJ and Maven compiles without any problem, just the method not resolvable in editor. What could be the problem?

Bad news, I think you must wait for that functionality. See this:
http://youtrack.jetbrains.com/issue/IDEA-59138
In short: Nowadays Intellij doesn't support AspectJ declare parents nor declare precedence
Intellij developers have been playing around with this feature since Intellij 11 (See the comments about No technical block, just lack of resources)
The issue is marked to be resolved on Intellij 14. How long is that? See that Intellij 13.1 is planned to be released on Q2 of 2014, so it will take a while.

Related

instanciating SolrCrudRepository programmatically, without Spring Boot magic

I have a Spring Boot 2.4 project that is using spring-boot-starter-data-solr. Unfortunately, spring-boot-starter-data-solr is not supported anymore (see https://spring.io/projects/spring-data-solr#overview) , so I can't easily upgrade Spring Boot as I usually do for other projects.
However, I thought I would still try to upgrade my project and keep using the latest spring-boot-starter-data-solr I could get : maybe it's not supported anymore, but I am not making an extensive use of it, so maybe I can take advantage of latest Spring Boot features for a some more time, before there's really a breaking change and I really can't use spring-boot-starter-data-solr
So, I upgraded my project to Spring Boot 2.6.4 letting Spring BOM pull all the latest versions of all dependencies managed. Of course, it failed on spring-boot-starter-data-solr, so I had to declare the version explicitly :
implementation 'org.springframework.boot:spring-boot-starter-data-solr:2.4.13'
I fixed few other things, and my project compiles. However, at startup (and in some integration tests), I have a problem :
#Configuration
public class PersistenceConfig {
#Bean
public TicketRepository ticketRepository(SolrTicketEntityRepository solrTicketEntityRepository) {
return new TicketRepositoryImpl(solrTicketEntityRepository);
}
... some other beans..
}
with SolrTicketEntityRepository defined like below :
public interface SolrTicketEntityRepository extends SolrCrudRepository<TicketEntity, String> {
#Query("?0")
Page<TicketEntity> search(String searchText, Pageable pageable);
With Spring Boot 2.6, the SolrTicketEntityRepository doesn't get instanciated anymore, so I have a missing bean at startup. I've tried adding the #EnableSolrRepositories on PersistenceConfig, but it doesn't do anything.
is there a way to mimic Spring Boot magic, and trigger programmatically SolrTicketEntityRepository / SolrCrudRepository instanciation, to be able to start my application ?
or is it way too complicated, and as recommended here , should I implement the stuff myself with the core Solr libraries without Spring Boot's help (which would be the objective at some point anyway) ?

Spring AOP (AspectJ) with Kotlin and Gradle - I can't get it to work

I have a Spring Boot + Kotlin + Gradle project. I'd like to create a small library for my use-cases. This library should use AOP to remove some cross cutting concerns I observed.
Therefore I started adding these two dependencies to my gradle build file.
build.gradle.kts
implementation("org.springframework:spring-aop:5.2.9.RELEASE")
implementation("org.springframework:spring-aspects:5.2.9.RELEASE")
I also added the freefair aspectj plugin due some suggestions from the interwebs.
The following aspect I created should be placed in src/main/aspectj according to this documentation: https://docs.freefair.io/gradle-plugins/5.2.1/reference/#_io_freefair_aspectj
This plugin adds AspectJ support to the project, by adding a aspectj directory to every source set.
Source contained in the src/main/aspectj directory will be compiled with ajc by the compileAspectj task.
plugins {
// ...
id("io.freefair.aspectj") version "5.2.1"
// ...
}
I then started to create my first aspect that matches on every method which is annotated with #Foozy
src/main/aspectj/FoozyAspect.kt < the 'special' source path
#Component
#Aspect
class FoozyAspect {
#Before("#annotation(com.client.annotation.Foozy)")
fun doStuff() {
LOG.info("Do Stuff")
}
companion object {
private val LOG = LoggerFactory.getLogger(FoozyAspect::class.java)
}
}
Then I created this annotation
src/main/kotlin/com.client.annotation/Foozy.kt
#Target(AnnotationTarget.FUNCTION)
annotation class Foozy
Now to test if everything works as expected I created a unit test
src/test/kotlin/FoozyAspectTest.kt
#SpringBootTest
#EnableAspectJAutoProxy
internal class FoozyAspectTest {
private val testCandidate: TestCandidate = TestCandidate()
#Test
fun `should work with aspect`() {
testCandidate.doStuff()
}
}
src/test/TestCandidate.kt
class TestCandidate {
#Foozy
fun doStuff(): String {
return "stuff"
}
}
Result
Executing the text in debug mode does not yield the awaited info log Do Stuff and also does not cease the thread at the breakpoint in the FoozyAspect.kt doStuff() method.
I have no idea what to configure here.
For good reason I kinda have the suspicion that I am mixing up different "ways" to get this to work or am just missing some final steps in preconfiguration/prerequisites.
The AspectJ compiler can't compile Kotlin source code. Your .kt file in src/main/aspectj will be completely ignored.
You have different options depending on what you really want to do:
Do you want your Aspect to be woven by ajc at compile-time, or do you just want to use "plain" Spring AOP?
The differences are explained here: https://docs.spring.io/spring-framework/docs/current/reference/html/core.html#aop-choosing
If you just want to use Spring AOP, you dont need a special gradle plugin. Just put your .kt file in src/main/kotlin and follow the Spring AOP docs.
If you want to weave your aspect at compile-time with ajc, you have two options:
Keep the io.freefair.aspectj plugin to compile an weave the aspect in one step: Implement your aspect as .java or .aj so it can be compiled by ajc
Switch to the io.freefair.aspectj.post-compile-weaving plugin in order to separate the compilation an weaving steps: In this case you can keep your Aspect implementation as Kotlin, but you have to put it in src/main/kotlin. Your Aspect will then be compiled by kotlinc and then woven by ajc.
This looks like the 347th duplicate of a classical Spring AOP question: If you read the manual, you will notice that Spring AOP only works for Spring components, e.g. declared via #Component or #Bean.
Your TestCandidate seems to be a POJO, so Spring does not know about it. Also if you make it a component, make sure you get an instance from the container and do not just create one via constructor call in your test.

Enabling compile-time AspecJ for Spring Method Security

Spring AOP runs everything through proxies which sadly can't be everywhere. For this reason Spring Security's annotations #PreAuthorize, #PostAuthorize, #PreFilter and #PostFilter (also #Secured) will not be taken into consideration when calls are not going through said proxies. Proxies are created only for singletons (#Beans) so We are greatly limited when We want to secure methods on specific objects (such as JPA #Entities) that are not beans. Proxies also won't be called within calling objects (bean calling its methods in context of self - this).
I know that Spring has suppot not only for Spring AOP but also real AOP - AspectJ. Not only that, but it SHOULD support AspectJ out of box. Testament to this is:
#EnableGlobalMethodSecurity(mode = AdviceMode.ASPECTJ, securedEnabled = true, prePostEnabled = true)
When enabled, Spring will require (crash on startup otherwise) aspectj dependency, which is provided within:
'org.springframework.security:spring-security-aspects'
After adding this dependency we will have AspectJ libraries in classpath and will get:
org.springframework.security.access.intercept.aspectj.aspect
with:
public aspect AnnotationSecurityAspect implements InitializingBean
But here it all ends. There is no documentation that I could find that would state how to further enable aspectj weaving. Setting #EnableGlobalMethodSecurity(mode = AdviceMode.ASPECTJ) certainly DOES something as we lose standard Spring AOP - security annotations stop working anywhere (on Beans) and at the same time they are not weaved with AspectJ.
Does anyone have some knowledge on Spring's support for this out of box (compile-time weaving) and what further configuration is needed? Maybe I need to weave it myself? Do I need some specific libraries for building?
Version: Spring 5.2.1.RELEASE (all packages).
#DimaSan comment helped me find few threads/issues I missed while doing my search and while many of them are too years-outdated I managed to setup my app.
Turns out I was actually very close and by making few updates and changing dependencies/plugins on gradle I have a working environment.
Gradle: 5.6.4
with:
plugins {
id "io.freefair.aspectj.post-compile-weaving" version "4.1.6"
}
dependencies {
aspect 'org.springframework.security:spring-security-aspects'
runtime 'org.springframework.security:spring-security-aspects'
}
Spring setup at 5.2.1.RELEASE with
spring-boot-starter-
web
data-jpa
security
With above setup this is actually only thing needed:
#EnableGlobalMethodSecurity(mode = AdviceMode.ASPECTJ, securedEnabled = true, prePostEnabled = true)
Finally if You are not using Gradle (e.g. want to use STS/Eclipse Run Configuration), you will add:
-javaagent:C:\Users\USER\.gradle\caches\modules-2\files-2.1\org.aspectj\aspectjweaver\1.9.4\<cache-string>\aspectjweaver-1.9.4.jar
.gradle and 1.9.4 being case for my current setup/version.
Note that this is yet untested (but working with JPA/Hibernate) with e.g. Transaction management and I will comment on it once I start using complex transactions where weaving would create issues.

Spring AOP aspect doesn't get applied if included from an external jar with different package name

I have a spring boot rest service that included an external project in pom as it's dependency. That external project is basically a jar that has spring AOP code.
The base package in my main application that includes this external jar with spring AOP code is x.y.z
The class in external jar where the #before advice is, is under the package a.b.c
With this class under a.b.c package, it doesn't get recognized by the main application where I want to use the spring aop implementation and apply the aspect. However, when I change it's package from a.b.c to x.y.z (which I really can't do in real life) it works fine.
I know that in spring boot service which happens to be the including service, it scans everything under root package given in the application class, x.y.z in this case and that is why aspect works fine if it's class is under x.y.z.
however, the problem is that this spring app jar will be used across multiple applications. So changing package name like this is not an option.
Is there a way to accomplish this without changing the package name of the class where spring app code is ?
Probably component scan is only activated for your application class packages by default. You can extend it to multiple packages, including the aspect package:
XML style configuration:
<context:component-scan base-package="x.y.z, a.b.c" />
Annotation style configuration:
#ComponentScan(basePackages = {"x.y.z", "a.b.c"})
Disclaimer: I am not a Spring user, only an AspectJ expert. I just knew that you can configure component scan, googled the syntax for you and hope it is correct.
Please define the bean (of jar project )inside main application. Give the #ComponentScan(basePackages = {"x.y.z", "a.b.c"}) as well as #EnableAspectJAutoProxy. Also include below piece of code.
ex:
` #Bean
public LoggingHandler loggingHandler()
{
return new LoggingHandler();
}`
Also annotate external jar code with:
`#Aspect
#Component
public class LoggingHandler {`
What #kriegaex suggests is correct. In addition to that, please make sure you are using #Component along with #Aspect. Since #Aspect is not a Spring annotation, Spring won't recognize it and hence your aspect won't be registered. So, using #Component is mandatory to getting aspects to work in Spring environment.

Using aspectj in Hibernate entity

I have entity class like this:
package tr.com.example.model.porting
...//omitting imports
#Configurable
#Data
#Entity
public class PortOut{
public void handleRequest(Long portingId) {
processRequest(portingId);
...
}
}
And here is my aspect code in different class annotated with #Aspect and #Component:
#Around("execution(* tr.com.example..PortOut.handleRequest(..))")
public void handlePortingProcessAdvice(ProceedingJoinPoint joinPoint) throws Throwable {
joinPoint.proceed();
log.debug(log.debug("[POM]:{} is executed with parameters:{}", joinPoint.toShortString(), joinPoint.getArgs()))
}
Normally, my aspect code works fine for other Spring managed classes such as using #Service, #Component annotation. I am using https://github.com/subes/invesdwin-instrument as a weaving agent and also using Lombok.
I tried this link(along with other so posts). But since I am using Lombok, I cannot directy compile with aspectj compiler for weaving #Configurable classes, it doesn't work with Lombok as I found out.
https://groups.google.com/forum/#!topic/project-lombok/ZkLsTZVSgD4
Shortly, what I want is using aspectj for logging some methods's arguments, but I can't use it in any Hibernate entity class, other than that it works fine. How to get it working in entity classes?
Here you find the explanation why Lombok and AspectJ do not like each other.
What is said to work though, is to delombok the Lombok-annotated source code and then normally compile the generated source code with the AspectJ compiler (e.g. via AspectJ Maven plugin, which is what I use all the time in Maven projects). Assuming you do use Maven, also the delombok step can be done with Lombok Maven plugin. If you assign the right phases to the respective plugins, it should be possible to fully automate the build process.
Disclaimer: I have never used Lombok in my whole life, but know a thing or two about AspectJ and Maven.

Resources