Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/wkgcass/pojo-agent
A tool which enhances your pojo, powered by java-agent.
https://github.com/wkgcass/pojo-agent
Last synced: about 2 months ago
JSON representation
A tool which enhances your pojo, powered by java-agent.
- Host: GitHub
- URL: https://github.com/wkgcass/pojo-agent
- Owner: wkgcass
- License: gpl-2.0
- Created: 2022-04-14T13:39:14.000Z (over 2 years ago)
- Default Branch: master
- Last Pushed: 2023-12-01T04:07:47.000Z (about 1 year ago)
- Last Synced: 2023-12-01T05:23:23.626Z (about 1 year ago)
- Language: Java
- Size: 150 KB
- Stars: 5
- Watchers: 1
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
# pojo-agent
A tool which enhances your pojo, powered by java-agent.
**maven**
```xml
io.vproxy
pojo-agent-api
1.2.0```
**gradle**
```groovy
implementation group: 'io.vproxy', name: 'pojo-agent-api', version: '1.2.0'
```## current supported functions
* Helps you know that a setter is invoked or not.
* Auto implement `updateFrom` method, which helps you assign properties from one entity to another.
* Auto property validation, supports `@MustExist`, `@MustNotExist`, `@MustNotNull`.## build
```
./gradlew clean jar
```The agent is in `build/libs/pojo-agent.jar`.
You can also get the pre-built agent in the release pages.## test
```
./gradlew clean suite
```## how to use
Works on java 8, 11, 17, 21, and kotlin.
### step 1
Add `@Pojo` annotation on you pojo:
```java
@Pojo
public class MyEntity {
private String id;
// getters ...
// setters ...
}
```or you can use `data class` if you are using kotlin:
```kotlin
@Pojo
data class MyEntity(
var id: String = ""
)
// getters and setters are generated by kotlin compiler
```#### step 1.1: updateFrom
You may let your entity class implement the template interface `PojoUpdateFrom`, or you can simply add methods with the same signatures defined in this interface.
* `preUpdateFrom` is optional, if defined, it will be called before calling `updateFrom`
* `postUpdateFrom` is optional, if defined, it will be called after calling `updateFrom`Both `preUpdateFrom` and `postUpdateFrom` are optional and can be private (if not implementing the `PojoUpdateFrom` template interface).
```java
@Pojo
public class MyEntity implements PojoUpdateFrom {
@PojoAutoImpl
@Override
public void updateFrom(SimpleEntity another) {
throw new RequirePojoAutoImplException();
}
}
```#### step 1.2: validate
You may let your entity class implement the template interface `PojoValidate`, or you can simply add methods with the same signatures defined in this interface.
* `preValidate` is optional, if defined, it will be called before calling `validate`
* `postValidate` is optional, if defined, it will be called after calling `validate`Both `preValidate` and `postValidate` are optional and can be private (if not implementing the `PojoValidate` template interface).
Add `@MustExist`, `@MustNotExist`, `@MustNotNull` annotations on fields which you want to validate. All these annotations takes one **optional** argument: an integer, which is a bit mask, which helps you specify what kind of validation is required when executing an action.
```java
import static io.vproxy.pojoagent.api.CommonActions.*;@Pojo
public class MyEntity implements PojoValidate {
@MustNotExist(ALL) // must not exist in any condition
private int id;@MustExist(CREATE) // must exist when creating
@MustNotExist(~CREATE) // must not exist except creating
@MustNotNull(CREATE) // must exist and must not be null when creating
private String name;@PojoAutoImpl
@Override
public ValidationResult validate(int action) {
throw new RequirePojoAutoImplException();
}// getters setters ...
}
```You may leave the annotation argument empty, which will be 0 by default, and use `entity.validate(0)` (or `entity.validate()` if you are implementing the template interface) to validate the entity.
The result of the `validate` method is a non-null object: `ValidationResult`.
#### step 1.3: setAllFields and unsetAllFields
Pojo-agent provides you a way to consider all fields are set or not set (if a field is `set`, the field existence assertion against that field will pass).
You may let your entity class implement the template interfaces `PojoSetAllFields` or `PojoUnsetAllFields`, or you can simply add methods with the same signatures defined in these interfaces.
```java
@Pojo
public class MyEntity implements PojoSetAllFields, PojoUnsetAllFields {
// fields ...
// getters setters ...@PojoAutoImpl
@Override
public void setAllFields() {
throw new RequirePojoAutoImplException();
}@PojoAutoImpl
@Override
public void unsetAllFields() {
throw new RequirePojoAutoImplException();
}
}
```### step 2
Add `@PojoCaller` on the method which uses functions in `PojoAgent` helper class:
```java
@PojoCaller
public void manipulateMyEntity(MyEntity entity) {
// ...
}
```### step 3
Use `PojoAgent` helper class in the `@PojoCaller` functions:
```java
// check whether a field is set
PojoAgent.fieldIsSet(entity.getId())// unset the field
PojoAgent.unsetField(entity.getId())
// then you will get `false` from `fieldIsSet` call after calling `unsetField`
// However note that the value of this property will not be modified, you can still get correct result from `getId()`// set the field without touching it's setter
PojoAgent.setField(entity.getId())
// then you will get `true` from `fieldIsSet` call after calling `setField`
```### step 4
Add `-javaagent:${path-to-pojo-agent.jar}` to your `java` command.
> If you are using java 17, you may need to add extra arguments: `--add-opens java.base/jdk.internal.org.objectweb.asm=ALL-UNNAMED --add-opens java.base/jdk.internal.org.objectweb.asm.tree=ALL-UNNAMED`
### optional
Add `PojoAgent.ensurePojoAgent();` to the entry of your application. This method will check and throw an exception if `pojo-agent` is not loaded.
## sample
The sample code is in `./sample/src/main/`
Run:
* `./gradlew clean sample`
* `./gradlew clean ktsample`to see the output.