728x90
[Rest][2023-08-02 18:39:02][ERROR][PostingController.java][lambda$doFindPostingActivity$5(92)] : readPosting
org.springframework.aop.AopInvocationException: Null return value from advice does not match primitive return type for: public abstract boolean net.infobank.moyamo.repository.PostingRepository.isPostingOwner(long,java.lang.Long)
        at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:229)
        at com.sun.proxy.$Proxy237.isPostingOwner(Unknown Source)
        at net.infobank.moyamo.service.PostingService.findPostingActivity(PostingService.java:1831)
        at net.infobank.moyamo.service.PostingService$$FastClassBySpringCGLIB$$72b2a0db.invoke(<generated>)
        at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:218)
        at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:779)
        at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:163)
        at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:750)
        at org.springframework.transaction.interceptor.TransactionInterceptor$1.proceedWithInvocation(TransactionInterceptor.java:123)
        at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:388)
        at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:119)
        at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
        at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:750)
        at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:692)
        at net.infobank.moyamo.service.PostingService$$EnhancerBySpringCGLIB$$886f7a7f.findPostingActivity(<generated>)
        at net.infobank.moyamo.controller.PostingController.lambda$doFindPostingActivity$4(PostingController.java:91)
        at java.util.concurrent.FutureTask.run(FutureTask.java:266)
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
        at java.lang.Thread.run(Thread.java:750)

 

Handling

The error message you are encountering (AopInvocationException: Null return value from advice does not match primitive return type) suggests that a method with a primitive return type (boolean in this case) is returning null. Since primitives cannot be null, this results in an exception.

Here's a brief rundown of what might be happening:

  1. Method Signature: The method isPostingOwner(long, java.lang.Long) in the PostingRepository interface is declared with a return type of boolean.
  2. Proxy Invocation: During the invocation, some AOP advice (such as a transactional aspect) may be being applied to this method.
  3. Null Return: For some reason, this method is returning null (possibly from a repository implementation or advice method), which is not compatible with the primitive boolean return type.

Here's how you can potentially resolve this:

1. Check the Repository Implementation

Ensure that the method's implementation in the corresponding repository class is not returning null. It should return a boolean value (true or false).

2. Check the AOP Advice

If there is any AOP (Aspect-Oriented Programming) advice being applied to the method, make sure that it's not altering the return value to null. Examine any aspects that might be affecting the method, including transactional aspects.

3. Change the Return Type (if applicable)

If it is acceptable for the method to indicate an absence of a value, consider changing the return type of the method from the primitive boolean to the wrapper class Boolean. This will allow the method to return null. Note that this will require handling the null value in the calling code.

Example:

javaCopy code
public abstract Boolean isPostingOwner(long id, java.lang.Long ownerId);

4. Exception Handling

If the null return is expected in some situations (like when some data is not found), consider adding proper exception handling in the method or its caller to deal with these scenarios gracefully.

By focusing on these areas, you should be able to track down the cause of the exception and resolve it. Make sure to thoroughly test your changes to ensure they don't introduce other issues.

 

 

 

JPOL 상에서 일치하지 않는 return type을 확인해서 boolean 에서 Boolean 으로 변경

@Query("select p.owner.id from Posting p where p.id = :postingId and p.owner.id = :userId")
Boolean isPostingOwner(@Param("postingId") long postingId, @Param("userId") Long userId);

 

추가적으로 null Pointer Exception handling

if(isWatch == null) {
    isWatch = !commentRepository.findDistinctRecipientByMentionUserIds(id, Collections.singletonList(user.getId())).isEmpty();
    Boolean isOwner = postingRepository.isPostingOwner(id, user.getId());
    isWatch = isWatch || (isOwner != null && isOwner);
}

 

을 했지만 문제발생으로 인한 JPQL 변경으로 처리

@Query("select case when count(p) > 0 then true else false end from Posting p where p.id = :postingId and p.owner.id = :userId")
Boolean isPostingOwner(@Param("postingId") long postingId, @Param("userId") Long userId);
728x90
dependencies {
    // Other dependencies...
    implementation 'com.slack.api:slack-java-api:2.10.0'
}

요로코롬 2.10.0 을 납치해주면 될 것 같지만 작동하지 않는다.

 

Gradle

Do you prefer using Gradle? Let’s try installing the library with Gradle. The steps are quite similar to Maven, but there are some differences.

build.gradle

Place build.gradle in the root directory of your Java project. We don’t have any requirements for Gradle versions.

plugins {
  id("application")
}
repositories {
  mavenCentral()
}
dependencies {
  implementation("com.slack.api:slack-api-client:1.30.0")
}
application {
  mainClassName = "Example"
}

As with the Maven section, let’s create a class named Example with the main method. Then, run it from your IDE or hit gradle run on your terminal. You’ll see the same stdout.

In summary, the things you’ve done here are:

  • ✅ JDK 8 or higher installed (if not, run brew install openjdk@11 for macOS / visit OpenJDK website for others)
  • ✅ Gradle installed (if not, run brew install gradle for macOS / visit their website for others)
  •  build.gradle having slack-api-client as a dependency
  •  src/main/java/Example.java with the main method

Gradle for Kotlin

 

 

위에처럼 1.30.0 에 대한 부분을 build.gradle 에 의존성 결과로 적용해준 이후에 import 할 수 있었다.

특히 코드에서 몇가지 없는 부분들이 있는데, 버전이 올라감에 따라서 .get method 등이 deprecated 되었다.

https://slack.dev/java-slack-sdk/guides/web-api-client-setup

 

Installation | Slack SDK for Java

API Client Installation The first step to using the Slack API client is installing the slack-api-client module. This guide shows you how to set up using Maven, Gradle, and by building from source on your own. Prerequisites Installing OpenJDK 8 or higher LT

slack.dev

 

728x90

The Cannot resolve table 'user_group' is a warning that's typically seen in IntelliJ IDEA, it's not actually an error. It happens because IntelliJ IDEA does not know about the existence of a table named user_group because it's an intermediary table created by Hibernate to manage @ManyToMany relationships, not a table that you've explicitly created yourself.

The Hibernate runtime knows to create the user_group table based on the configuration in your User entity, but IntelliJ IDEA's static code analysis doesn't know this, and so it raises a warning.

You can safely ignore this warning. When you run your application, Hibernate will automatically create the user_group table for you.

However, if you want to get rid of this warning in IntelliJ IDEA, you can use the JPA Console to update the IntelliJ IDEA schema:

  1. Open the Persistence tool window by going to View -> Tool Windows -> Persistence.
  2. Click on the JPA Console tool button.
  3. In the JPA Console, execute this command: update

This will update the IntelliJ IDEA schema with your Hibernate/JPA schema and the warning should go away. Please ensure that you have correctly set up the data source in IntelliJ IDEA.

Remember, Cannot resolve table is a warning from the IDE and not an error from the Java compiler or the runtime environment. Your code should compile and run correctly despite this warning.

728x90

JPA 는 ORM 으로써 내부적으로 별도로 선언하지 않은 부분에 대해서 자동으로 만들어준다는 점에 의해서 굉장히 예쁘고 사랑스럽지만 종종 개같은 경우를 만들 때가 있다.

 

그 중 하나가 미리 예약된 예약어 같은 케이스인데, 그런 예약어를 보게 된다면 아래와같은 에러를 마주칠 수가 있다.

로그를 한땀한땀 해석해보자면, GenerationTarget (생성하려는 대상)이 명령어를 수용하는 도중에 예외에 맞닥들였다는 것이다. 특히 이 부분에서 DDL "alter table if exists group_users add constraint xxxx" 라고 나오는데 문제가 되는 부분이 바로

"group_users" 가 되시겠다.

 

group 은 사실 스프링 예약어라기 보다는 SQL 에서 예약된 예약어로써 다들 알다시피 group by 에서 납치해다 쓰는 경우가 많은데, 이 때문에 생성하면서 alter table 로 외래키 제약조건을 생성하려다가 망할놈의 에러를 만난 것이다

 


그래서 어떻게 해결하는데?

약 2가지 정도의 해결 방법이 떠오르는데, 첫번째 방법은 그냥 감싸주는 것이다.

 

@Entity
@Table(name = "article")
public class Article {
	@Id
	private Long id;
	private String title;
	private String description;
	
	@Column(name = "\"group\"")
	private String group;
}

예를 들어 내부에 정의된 속성 중 group 이라는 놈이 걸릴꺼니까 저렇게 감싸버리고, 그리고 다른 경우에 Entity 하위에 나와같이 Table 명 자체를 group으로 주고 싶은 경우에는 @Table(name = "\"group\"") 과 같이 주면 되겟다.

 

그런데 이 짓거리를 언제 다 하냐 이말이지.

그래서 나온 것이 application.properties 쪽이나 yml 에서 떄려잡는 것이다.

 

spring:
  jpa:
    properties:
      hibernate:
        globally_quoted_identifiers: true # 이 설정을 추가해준다.
        show_sql: true # 쿼리를 출력해준다.
        format_sql: true # 쿼리를 예쁘게 출력해준다.
        generate_statistics: true # 쿼리 수행 통계를 확인할 수 있다.

 

properties 쪽에서 때려잡은 나는 아랫쪽의 것을 사용해줫다

# 이 설정을 추가해준다.
spring.jpa.properties.hibernate.globally_quoted_identifiers=true

# 참고로 아래 설정은 실행된 SQL 쿼리를 출력해준다.
spring.jpa.properties.hibernate.show_sql=true
spring.jpa.properties.hibernate.format_sql=true

# 쿼리 수행 통계를 확인할 수 있다.
spring.jpa.properties.hibernate.generate_statistics=true


결론 = 데이터베이스 예약어나 키워드를 Entity 가 정의된 클래스에서 사용하지 말자

+ Recent posts