Skip to content

Commit

Permalink
Ethlo back (eclipse-hawkbit#2267)
Browse files Browse the repository at this point in the history
* Return Ethlo plugin

* Return back statick weaving for EclipseLink in order to use lazy fetch
  • Loading branch information
avgustinmm authored Feb 11, 2025
1 parent 4ded430 commit 1e4e45f
Show file tree
Hide file tree
Showing 14 changed files with 294 additions and 131 deletions.
12 changes: 5 additions & 7 deletions hawkbit-repository/hawkbit-repository-jpa-api/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,11 @@
<version>${project.version}</version>
</dependency>

<dependency>
<groupId>jakarta.persistence</groupId>
<artifactId>jakarta.persistence-api</artifactId>
</dependency>

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
Expand All @@ -43,12 +48,5 @@
</exclusion>
</exclusions>
</dependency>

<!-- Static class generation -->
<dependency>
<groupId>org.hibernate.orm</groupId>
<artifactId>hibernate-jpamodelgen</artifactId>
<optional>true</optional>
</dependency>
</dependencies>
</project>

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
# hawkBit JPA EclipseLink Vendor integration

Implementation of [EclipseLink](http://www.eclipse.org/eclipselink/) JPA vendor.
Implementation of [EclipseLink](http://www.eclipse.org/eclipselink/) JPA vendor.

Since there seem to be bug in eclipselink static weaver or eclipselink-maven-plugin - don't weave properly the abstract classes when no non-abstract entity into the maven module - we use to have fake entity in the module to make it work.
29 changes: 29 additions & 0 deletions hawkbit-repository/hawkbit-repository-jpa-eclipselink/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -52,4 +52,33 @@
<version>${eclipselink.version}</version>
</dependency>
</dependencies>

<build>
<plugins>
<!-- Static weaver for EclipseLink -->
<plugin>
<groupId>com.ethlo.persistence.tools</groupId>
<artifactId>eclipselink-maven-plugin</artifactId>
<version>${eclipselink.maven.plugin.version}</version>
<executions>
<execution>
<phase>process-classes</phase>
<goals>
<goal>weave</goal>
</goals>
</execution>
</executions>
<configuration>
<basePackage>org.eclipse.hawkbit.repository.jpa.model</basePackage>
</configuration>
<dependencies>
<dependency>
<groupId>org.eclipse.persistence</groupId>
<artifactId>org.eclipse.persistence.jpa</artifactId>
<version>${eclipselink.version}</version>
</dependency>
</dependencies>
</plugin>
</plugins>
</build>
</project>
Original file line number Diff line number Diff line change
Expand Up @@ -14,29 +14,39 @@
import jakarta.persistence.Access;
import jakarta.persistence.AccessType;
import jakarta.persistence.Column;
import jakarta.persistence.EntityListeners;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;
import jakarta.persistence.MappedSuperclass;
import jakarta.persistence.PostPersist;
import jakarta.persistence.PostRemove;
import jakarta.persistence.PostUpdate;
import jakarta.persistence.Version;

import lombok.AccessLevel;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import org.eclipse.hawkbit.repository.jpa.model.helper.AfterTransactionCommitExecutorHolder;
import org.eclipse.hawkbit.repository.model.BaseEntity;
import org.eclipse.hawkbit.tenancy.TenantAwareAuthenticationDetails;
import org.springframework.data.annotation.CreatedBy;
import org.springframework.data.annotation.CreatedDate;
import org.springframework.data.annotation.LastModifiedBy;
import org.springframework.data.annotation.LastModifiedDate;
import org.springframework.data.jpa.domain.support.AuditingEntityListener;
import org.springframework.security.core.context.SecurityContextHolder;

/**
* Base hawkBit entity class containing the common attributes for EclipseLink.
*/
@NoArgsConstructor(access = AccessLevel.PROTECTED) // Default constructor needed for JPA entities.
@MappedSuperclass
@EntityListeners({ AuditingEntityListener.class, EntityInterceptorListener.class })
// exception squid:S2160 - BaseEntity equals/hashcode is handling correctly for sub entities
@SuppressWarnings("squid:S2160")
public abstract class AbstractJpaBaseEntity extends AbstractBaseEntity {
public abstract class AbstractJpaBaseEntity implements BaseEntity {

protected static final int USERNAME_FIELD_LENGTH = 64;

Expand Down Expand Up @@ -116,4 +126,86 @@ public void setLastModifiedAt(final long lastModifiedAt) {
public long getLastModifiedAt() {
return lastModifiedAt == 0 ? createdAt : lastModifiedAt;
}

/**
* Defined equals/hashcode strategy for the repository in general is that an entity is equal if it has the same {@link #getId()} and
* {@link #getOptLockRevision()} and class.
*/
@Override
// Exception squid:S864 - generated code
@SuppressWarnings({ "squid:S864" })
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + (getId() == null ? 0 : getId().hashCode());
result = prime * result + getOptLockRevision();
result = prime * result + getClass().getName().hashCode();
return result;
}

/**
* Defined equals/hashcode strategy for the repository in general is that an entity is equal if it has the same {@link #getId()} and
* {@link #getOptLockRevision()} and class.
*/
@Override
public boolean equals(final Object obj) {
if (this == obj) {
return true;
}
if (obj == null) {
return false;
}
if (!getClass().isInstance(obj)) {
return false;
}
final BaseEntity other = (BaseEntity) obj;
final Long id = getId();
final Long otherId = other.getId();
if (id == null) {
if (otherId != null) {
return false;
}
} else if (!id.equals(otherId)) {
return false;
}
return getOptLockRevision() == other.getOptLockRevision();
}

@Override
public String toString() {
return getClass().getSimpleName() + " [id=" + getId() + "]";
}

@PostPersist
public void postInsert() {
if (this instanceof EventAwareEntity eventAwareEntity) {
doNotify(eventAwareEntity::fireCreateEvent);
}
}

@PostUpdate
public void postUpdate() {
if (this instanceof EventAwareEntity eventAwareEntity) {
doNotify(eventAwareEntity::fireUpdateEvent);
}
}

@PostRemove
public void postDelete() {
if (this instanceof EventAwareEntity eventAwareEntity) {
doNotify(eventAwareEntity::fireDeleteEvent);
}
}

protected static void doNotify(final Runnable runnable) {
// fire events onl AFTER transaction commit
AfterTransactionCommitExecutorHolder.getInstance().getAfterCommit().afterCommit(runnable);
}

protected boolean isController() {
return SecurityContextHolder.getContext().getAuthentication() != null
&& SecurityContextHolder.getContext().getAuthentication()
.getDetails() instanceof TenantAwareAuthenticationDetails tenantAwareDetails
&& tenantAwareDetails.isController();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ public void postUpdate(final DescriptorEvent event) {
final Object object = event.getObject();
if (((UpdateObjectQuery) event.getQuery()).getObjectChangeSet().getChangedAttributeNames().stream()
.anyMatch(field -> !TARGET_UPDATE_EVENT_IGNORE_FIELDS.contains(field))) {
AbstractBaseEntity.doNotify(((EventAwareEntity) object)::fireUpdateEvent);
AbstractJpaBaseEntity.doNotify(((EventAwareEntity) object)::fireUpdateEvent);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
/**
* Copyright (c) 2015 Bosch Software Innovations GmbH and others
*
* This program and the accompanying materials are made
* available under the terms of the Eclipse Public License 2.0
* which is available at https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*/
package org.eclipse.hawkbit.repository.jpa.model;

import java.io.Serial;

import jakarta.persistence.Entity;
import jakarta.persistence.Table;

import lombok.NoArgsConstructor;

/**
* Fake JPA entity to allow proper static compilation. It seems that if there is no actual (class) entity using AbstractJpaBaseEntity,
* the static compilation is not proper.
*/
@NoArgsConstructor(access = lombok.AccessLevel.PACKAGE)
@Table(name = "fake_for_static_compilation")
@Entity
public class FakeJpaEntityForStaticCompilation extends AbstractJpaTenantAwareBaseEntity {

@Serial
private static final long serialVersionUID = 1L;
}
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
<artifactId>hawkbit-repository-jpa-api</artifactId>
<version>${project.version}</version>
</dependency>

<dependency>
<groupId>org.hibernate.orm</groupId>
<artifactId>hibernate-core</artifactId>
Expand Down
Loading

0 comments on commit 1e4e45f

Please sign in to comment.