Field #Inject not working in Dagger2 - java

I am new to CDI with Dagger. I have the following structure. The issue is when I go to fetch backendService in class Main, only the direct backendService is fetched, but the underlying User dependency remains null. Is there anything wrong with this setup.
Class MyComponent
import javax.inject.Singleton;
import dagger.Component;
#Singleton
#Component(modules = {UserModule.class, BackEndServiceModule.class})
public interface MyComponent {
User user();
BackendService backendService();
void inject(Main main);
void injectIntoBackendService(BackendService backendService);
}
Class User:
import javax.inject.Inject;
public class User {
private String firstName;
private String lastName;
public User(String firstName, String lastName) {
this.firstName = firstName;
this.lastName = lastName;
}
#Override
public String toString() {
return "User [firstName=" + firstName + ", lastName=" + lastName + "]";
}
}
Class UserModule
import javax.inject.Singleton;
import dagger.Module;
import dagger.Provides;
#Module
public class UserModule {
#Provides #Singleton User providesUser() {
return new User("Lars", "Vogel");
}
}
BackendService
import javax.inject.Inject;
import javax.inject.Named;
public class BackendService {
#Inject public User user;
private String serverUrl;
#Inject
public BackendService(#Named("serverUrl") String serverUrl) {
this.serverUrl = serverUrl;
}
public boolean callServer() {
System.out.println("User: " + user);
if (user !=null && serverUrl!=null && serverUrl.length()>0) {
System.out.println("User: " + user + " ServerUrl: " + serverUrl);
return true;
}
return false;
}
}
BackEndServiceModule
import javax.inject.Named;
import javax.inject.Singleton;
import dagger.Module;
import dagger.Provides;
#Module
public class BackEndServiceModule {
#Provides
#Singleton
BackendService provideBackendService(#Named("serverUrl") String serverUrl) {
return new BackendService(serverUrl);
}
#Provides
#Named("serverUrl")
String provideServerUrl() {
return "http://www.vogella.com";
}
#Provides
#Named("anotherUrl")
String provideAnotherUrl() {
return "http://www.google.com";
}
}
Main
import javax.inject.Inject;
public class Main {
#Inject public BackendService backendService;
public void callService() {
boolean callServer = backendService.callServer();
if (callServer) {
System.out.println("Server call was successful. ");
} else {
System.out.println("Server call failed. ");
}
}
public static void main(String[] args) {
Main m = new Main();
MyComponent component = DaggerMyComponent.builder().build();
component.inject(m);
m.callService();
}
}

Please have a look at field injection vs constructor injection. You try to use both partially, ending up to use neither.
#Singleton
#Component(modules = {UserModule.class, BackEndServiceModule.class})
public interface MyComponent {
User user();
BackendService backendService();
void inject(Main main);
// you don't need that if you create the object!
// void injectIntoBackendService(BackendService backendService);
}
When in doubt, use constructor injection. As the name suggests..define dependencies in the constructor and get rid of any other #Inject.
#Singleton // add singleton here, use constructor injection!
public class BackendService {
public User user;
private String serverUrl;
#Inject
public BackendService(#Named("serverUrl") String serverUrl, User user) {
this.serverUrl = serverUrl;
this.user = user;
}
}
And when you don't need any further setup you don't need any #Provides annotated methods either, so get rid of provideBackendService(#Named("serverUrl") String serverUrl) please. We specified the scope on the implementation class above.
I also wrote an article about a few basic things to keep in mind when using Dagger.

Related

Spring Boot Postman 404 and Not Found Error

I am trying to create a Spring Boot program where I can save different products that a business may have for sale. I am saving the products into MongoDB.
Currently, I am trying to use PostMan to save a product into the database. However, PostMan keeps giving me this error, and I was wondering what I am doing wrong (this is the URL I am inputting into PostMan: "http://localhost:8080/mdb-spring-boot-product-organizer/api/addProduct"):
{
"timestamp": "2022-12-07T22:56:33.866+00:00",
"status": 404,
"error": "Not Found",
"path": "/mdb-spring-boot-product-organizer/api/addProduct"
}
Project Explorer
Controller Code
package com.example.mdbspringbootproductorganizer.controller;
import java.util.List;
import java.util.Optional;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import com.example.mdbspringbootproductorganizer.model.Product;
import com.example.mdbspringbootproductorganizer.repository.ProductRepository;
#RestController
#RequestMapping("/api")
public class ProductController {
#Autowired
private ProductRepository repository;
#PostMapping("/addProduct")
public String saveProduct(#RequestBody Product product) {
repository.save(product);
return "Added product with id : " + product.getId();
}
#GetMapping("/findAllProducts")
public List<Product> getProducts() {
return repository.findAll();
}
#GetMapping("/findAllProducts/{id}")
public Optional<Product> getProduct(#PathVariable int id) {
return repository.findById(id);
}
#DeleteMapping("/delete/{id}")
public String deleteBook(#PathVariable int id) {
repository.deleteById(id);
return "Product deleted with id: " + id;
}
}
Repository
package com.example.mdbspringbootproductorganizer.repository;
import org.springframework.data.mongodb.repository.MongoRepository;
import com.example.mdbspringbootproductorganizer.model.Product;
public interface ProductRepository extends MongoRepository<Product, Integer> {
}
POJO
package com.example.mdbspringbootproductorganizer.model;
import org.springframework.data.annotation.Id;
import org.springframework.data.mongodb.core.mapping.Document;
#Document(collection = "ProductInventory")
public class Product {
#Id
private int id;
private String name;
private double listedPrice;
private double purchasePrice;
private String condition;
private String brand;
private char shelf;
private int bin;
public Product(int id, String name, double listedPrice, double purchasePrice, String condition, String brand,
char shelf, int bin) {
super();
this.id = id;
this.name = name;
this.listedPrice = listedPrice;
this.purchasePrice = purchasePrice;
this.condition = condition;
this.brand = brand;
this.shelf = shelf;
this.bin = bin;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public double getListedPrice() {
return listedPrice;
}
public void setListedPrice(double listedPrice) {
this.listedPrice = listedPrice;
}
public double getPurchasePrice() {
return purchasePrice;
}
public void setPurchasePrice(double purchasePrice) {
this.purchasePrice = purchasePrice;
}
public String getCondition() {
return condition;
}
public void setCondition(String condition) {
this.condition = condition;
}
public String getBrand() {
return brand;
}
public void setBrand(String brand) {
this.brand = brand;
}
public char getShelf() {
return shelf;
}
public void setShelf(char shelf) {
this.shelf = shelf;
}
public int getBin() {
return bin;
}
public void setBin(int bin) {
this.bin = bin;
}
#Override
public String toString() {
return "Product [idNumber=" + id + ", name=" + name + ", listedPrice=" + listedPrice + ", purchasePrice="
+ purchasePrice + ", condition=" + condition + ", brand=" + brand + ", shelf=" + shelf + ", bin=" + bin
+ "]";
}
}
Main class
package com.example.mdbspringbootproductorganizer;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.data.mongodb.repository.config.EnableMongoRepositories;
#SpringBootApplication
#EnableMongoRepositories
public class MdbSpringBootApplication {
public static void main(String[] args) {
SpringApplication.run(MdbSpringBootApplication.class, args);
}
}````
I have been trying to add different annotations or rename my packages, but none of that has worked.
I don't think mdb-spring-boot-product-organizer should be part of the URL.
Try making a POST to http://localhost:8080/api/addProduct.
Try adding #ComponentScan to your Spring boot application class.
#SpringBootApplication
#EnableMongoRepositories
#ComponentScan(basePackages={"com.example.mdbspringbootproductorganizer.controller","com.example.mdbspringbootproductorganizer.repository"})
public class MdbSpringBootApplication {
public static void main(String[] args) {
SpringApplication.run(MdbSpringBootApplication.class, args);
}
}
This error comes usually when your spring boot application cannot find the URL (since it is defined in different package than one with #SpringBootApplication class) despite defined in Controller!

Consuming JSON that may return a different data

I'd like to write some java code using spring boot to consume JSON data from a specific endpoint. However with each request the response may return different data fields as such.
{"success":true,"terms":"https:\/\/coinlayer.com\/terms","privacy":"https:\/\/coinlayer.com\/privacy","timestamp":1645616586,"target":"USD","rates":{"BTC":39049.424242}}
{"success":true,"terms":"https:\/\/coinlayer.com\/terms","privacy":"https:\/\/coinlayer.com\/privacy","timestamp":1645626666,"target":"USD","rates":{"BTC":39061.184046,"ETH":2726.545731}}
{"success":true,"terms":"https:\/\/coinlayer.com\/terms","privacy":"https:\/\/coinlayer.com\/privacy","timestamp":1645626966,"target":"USD","rates":{"ADA":0.939301,"BTC":39006.990707,"ETH":2720.502765}}
and so on.
Below is my current code which deals with the first case presented. I could write another Rates.java to cater for the second case and so on but I'm looking to have one Rates.java file which deals with all possible cases.
LiveData.java
package com.example.consumingrest;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
#JsonIgnoreProperties(ignoreUnknown = true)
public class LiveData {
private Boolean success;
private String terms;
private String privacy;
private Long timestamp;
private String target;
private Rates rates;
public LiveData() {
}
public Boolean getSuccess() {
return success;
}
public void setSuccess(Boolean success) {
this.success = success;
}
public String getTerms() {
return terms;
}
public void setTerms(String terms) {
this.terms = terms;
}
public String getPrivacy() {
return privacy;
}
public void setPrivacy(String privacy) {
this.privacy = privacy;
}
public Long getTimestamp() {
return timestamp;
}
public void setTimestamp(Long timestamp) {
this.timestamp = timestamp;
}
public String getTarget() {
return target;
}
public void setTarget(String target) {
this.target = target;
}
public Rates getRates() {
return rates;
}
public void setValue(Rates rates) {
this.rates = rates;
}
#Override
public String toString() {
return "LiveData{" +
"success='" + success + '\'' +
"terms='" + terms + '\'' +
"privacy='" + privacy + '\'' +
"timestamp='" + timestamp + '\'' +
"target='" + target + '\'' +
"rates=" + rates +
'}';
}
}
Rates.java
package com.example.consumingrest;
import java.math.BigDecimal;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonProperty;
#JsonIgnoreProperties(ignoreUnknown = true)
public class Rates {
#JsonProperty(value = "BTC")
private BigDecimal btc;
public Rates() {
}
public BigDecimal getBTC() {
return this.btc;
}
public void setId(BigDecimal btc) {
this.btc = btc;
}
#Override
public String toString() {
return "{" +
"BTC='" + btc + '\''+
'}';
}
}
ConsumingRest.java (main)
package com.example.consumingrest;
import java.time.LocalDate;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.web.client.RestTemplateBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.web.client.RestTemplate;
#SpringBootApplication
public class ConsumingRestApplication {
private static final Logger log = LoggerFactory.getLogger(ConsumingRestApplication.class);
public static void main(String[] args) {
SpringApplication.run(ConsumingRestApplication.class, args);
}
#Bean
public RestTemplate restTemplate(RestTemplateBuilder builder) {
return builder.build();
}
#Bean
public CommandLineRunner run(RestTemplate restTemplate) throws Exception {
return args -> {
LiveData liveData = restTemplate.getForObject(
"http://api.coinlayer.com/api/live?access_key=121a4df8b95fd5be872da3bad101cd73&target=EUR&symbols=BTC", LiveData.class);
log.info(liveData.toString());
};
}
}
As mentioned in the comments, seems you want a map containing the rates:
#JsonIgnoreProperties(ignoreUnknown = true)
public class LiveData {
...
private Map<String, BigDecimal> rates;
See Mapping a Dynamic JSON Object
Any Json Object can be parsed to Map<String, Object> where Object may be anything including Map or List. So, your map may be nested with any depth and it can contain Lists with any objects including maps. Any of your responses can be always parsed to that structure. So, return that structure and you won't have to worry about different formats - This is one size fits all.

How to implement proxy pattern?

I'm trying to understand how to make and use a proxy design pattern. I have no idea what am i doing wrong. Any suggestions would be appreciated:
Load method should simulate downloading configuration from remote server... and it kinda does. The 2 seconds delay should be launched just once, and then it should go smoothly.
public interface ConfigLoader {
String load();
}
RealObject
import lombok.Getter;
import lombok.Setter;
import org.apache.commons.lang3.RandomStringUtils;
import pl.sdacademy.prog.streams.MyExepction;
#Getter
#Setter
public class ConfigLoaderImplementation implements ConfigLoader {
private String configuration;
private String serverUrl;
public ConfigLoaderImplementation(final String serverUrl) {
this.serverUrl = serverUrl;
}
#Override
public String load() {
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
throw new MyException("Sleeping canceled!", e);
}
System.out.println("Configuration from " + getServerUrl() + " downloaded successfully");
String generatedConfiguration = RandomStringUtils.randomAlphabetic(10);
setConfiguration(generatedConfiguration);
return generatedConfiguration;
}
}
Proxy
import lombok.Data;
#Data
public class ConfigLoaderProxy implements ConfigLoader {
private ConfigLoader proxy;
public ConfigLoaderProxy(String url) {
this.proxy = proxy;
}
#Override
public String load() {
if (proxy == null) {
proxy = new ConfigLoaderImplementation("www.blablA.com");
return proxy.load();
} else {
return proxy.load();
}
//todo
}
}
Test class, with main
public class ConfigLoaderDemo {
public static void main(String[] args) {
ConfigLoader proxy = new ConfigLoaderProxy("sdasd");
proxy.load();
proxy.load();
proxy.load();
}
}
public class ConfigLoaderProxy implements ConfigLoader {
private final ConfigLoader configLoader;
private String configuration;
public ConfigLoaderProxy(final ConfigLoader configLoader) {
this.configLoader = configLoader;
}
#Override
public String load() {
if (configuration == null) {
configuration = configLoader.load();
}
return configuration;
}
}

How to get an instance of #Component in Spring?

I've a #Container class called RegistrationValidator that depends on a spring #Repository. Getting an instance of it in a service or another container through autowiring is fine, but I need access to it in a regular POJO. How can I get an instance of this validator without converting all POJOs to #Container or #Service objects. Is there a way to add a static getInstance method within the RegistrationValidator that returns an instance.
package core.dao.validator;
import core.dao.Registration;
import core.repository.RegistrationRepository;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Component;
import org.springframework.validation.Errors;
import org.springframework.validation.ValidationUtils;
import org.springframework.validation.Validator;
/**
* Validates the Registration DAO.
*
* #author Srini Katragadda
*/
#Component
public class RegistrationValidator implements Validator {
private static final Logger LOGGER = LoggerFactory.getLogger(RegistrationValidator.class);
private static final int MAX_SIZE = 255;
private final RegistrationRepository repository;
#Autowired
RegistrationValidator(RegistrationRepository repository) {
this.repository = repository;
}
#Override
public boolean supports(Class clazz) {
return Registration.class.equals(clazz);
}
#Override
public void validate(Object obj, Errors errors) {
Registration registration = (Registration) obj;
// Validate Message Id
ValidationUtils.rejectIfEmpty(errors, "messageId", "messageId.empty");
if (registration.getMessageId() != null &&
registration.getMessageId().length() > MAX_SIZE)
errors.rejectValue("messageId", "Size greater than " + MAX_SIZE);
// Validate for duplicate messageId information
if (hasDuplicateMessageIdInDatabase(registration)) {
errors.rejectValue("callouts", "Database has duplicate registration with messageId.");
}
}
/**
* Check if there is duplicate messageId in database.
*/
private boolean hasDuplicateMessageIdInDatabase(Registration adsRegistration) {
return (repository.findByMessageId(adsRegistration.getMessageId()) != null);
}
}
Here is where I need an instance of that validator. Checkout the Builder.build() method which is passing an instance of validator to a utility method. This worked fine until I needed to autowire a #Repository in RegistrationValidator. Now I need to pass the instance of repository to be able to construct the validator and was wondering how without making the DAO itself another component and autowiring it with RegistrationValidator.
package core.dao;
import core.dao.validator.RegistrationValidator;
import core.util.ValidatorUtil;
import core.util.ToString;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
/**
* The data access object that holds the information of an Registration.
*/
#JsonIgnoreProperties(ignoreUnknown = true)
public final class Registration {
private String id;
private String messageId;
private String version;
public Registration() {
}
private Registration(Builder builder) {
this.id = builder.id;
this.messageId = builder.messageId;
this.version = builder.version;
}
public static Builder getBuilder() {
return new Builder();
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getMessageId() {
return messageId;
}
public void setMessageId(String messageId) {
this.messageId = messageId;
}
public String getVersion() {
return version;
}
public void setVersion(String version) {
this.version = version;
}
/**
* Builder pattern makes the object easier to construct in one line.
*/
public static class Builder {
private String id;
private String messageId;
private String version;
private Builder() {}
public Builder id(String id) {
this.id = id;
return this;
}
public Builder messageId(String messageId) {
this.messageId = messageId;
return this;
}
public Builder version(String version) {
this.version = version;
return this;
}
public Registration build() {
Registration entry = new Registration(this);
return (Registration) ValidatorUtil.validate(entry, new RegistrationValidator());
}
}
}
Here is ValidatorUtil.validate code for completeness.
public static Object validate(Object entry, org.springframework.validation.Validator customValidator) {
Errors errors = new BeanPropertyBindingResult(entry, entry.getClass().getName());
customValidator.validate(entry, errors);
if (errors == null || errors.getAllErrors().isEmpty())
return entry;
else {
LOGGER.error(errors.toString());
throw new InvalidDataException(errors.getAllErrors().toString(), errors);
}
}
You could autowire spring bean into pojo with the SpringBeanAutowiringSupport, in the following way:
public class Pojo {
#Autowired
private RegistrationRepository repository
public void methodWhichRequiresBean() {
SpringBeanAutowiringSupport.processInjectionBasedOnCurrentContext(this);
repository.doStuff()
}
Hope this helps

Using user id with other model classes

I am using the play-authenticate plugin in my play-framework project. I want to be able to use the user ID (of the user currently logged in) from the User.java model class of the plugin.
#Id
public Long id;
I want to do this so that when users are creating entries in a separate model class I can store the user who has created these entries. Is there functionality in place to access this information or would I need to write an additional method in the User class to return the active user?
package controllers;
import java.text.SimpleDateFormat;
import java.util.Date;
import models.*;
import models.User;
import play.Routes;
import play.data.Form;
import play.mvc.*;
import play.mvc.Http.Response;
import play.mvc.Http.Session;
import providers.MyUsernamePasswordAuthProvider;
import providers.MyUsernamePasswordAuthProvider.MyLogin;
import providers.MyUsernamePasswordAuthProvider.MySignup;
import play.data.*;
import views.html.*;
import play.*;
import be.objectify.deadbolt.actions.Restrict;
import com.feth.play.module.pa.PlayAuthenticate;
import com.feth.play.module.pa.providers.password.UsernamePasswordAuthProvider;
public class Application extends Controller {
/*Part of the Play-Authenticate authentication plugin for the Play Framework.*/
public static final String FLASH_MESSAGE_KEY = "message";
public static final String FLASH_ERROR_KEY = "error";
public static final String USER_ROLE = "user";
public static User getLocalUser(final Session session) {
final User localUser = User.findByAuthUserIdentity(PlayAuthenticate
.getUser(session));
return localUser;
}
/*Source: https://github.com/joscha/play-authenticate*/
#Restrict(Application.USER_ROLE)
public static Result restricted() {
final User localUser = getLocalUser(session());
return ok(journeyManagement.render(localUser));
}
/*Source: https://github.com/joscha/play-authenticate*/
#Restrict(Application.USER_ROLE)
public static Result profile() {
final User localUser = getLocalUser(session());
return ok(profile.render(localUser));
}
/*Source: https://github.com/joscha/play-authenticate*/
public static Result login() {
return ok(login.render(MyUsernamePasswordAuthProvider.LOGIN_FORM));
}
/*Source: https://github.com/joscha/play-authenticate*/
public static Result doLogin() {
com.feth.play.module.pa.controllers.Authenticate.noCache(response());
final Form<MyLogin> filledForm = MyUsernamePasswordAuthProvider.LOGIN_FORM
.bindFromRequest();
if (filledForm.hasErrors()) {
// User did not fill everything properly
return badRequest(login.render(filledForm));
} else {
// Everything was filled
return UsernamePasswordAuthProvider.handleLogin(ctx());
}
}
/*Source: https://github.com/joscha/play-authenticate*/
public static Result signup() {
return ok(signup.render(MyUsernamePasswordAuthProvider.SIGNUP_FORM));
}
/*Source: https://github.com/joscha/play-authenticate*/
public static Result jsRoutes() {
return ok(
Routes.javascriptRouter("jsRoutes",
controllers.routes.javascript.Signup.forgotPassword()))
.as("text/javascript");
}
/*Source: https://github.com/joscha/play-authenticate*/
public static Result doSignup() {
com.feth.play.module.pa.controllers.Authenticate.noCache(response());
final Form<MySignup> filledForm = MyUsernamePasswordAuthProvider.SIGNUP_FORM
.bindFromRequest();
if (filledForm.hasErrors()) {
// User did not fill everything properly
return badRequest(signup.render(filledForm));
} else {
// Everything was filled
// do something with your part of the form before handling the user
// signup
return UsernamePasswordAuthProvider.handleSignup(ctx());
}
}
/*Source: https://github.com/joscha/play-authenticate*/
public static String formatTimestamp(final long t) {
return new SimpleDateFormat("yyyy-dd-MM HH:mm:ss").format(new Date(t));
}
}
Update:
package models;
import play.mvc.Http.Session;
import controllers.*;
import java.util.*;
import play.db.ebean.*;
import play.data.validation.Constraints.*;
import javax.persistence.*;
import play.data.format.*;
import com.avaje.ebean.*;
import java.text.*;
#Entity
public class Journey extends Model {
public SimpleDateFormat simpleTimeFormat = new SimpleDateFormat("hh:mm");
public SimpleDateFormat simpleDateFormat = new SimpleDateFormat("dd/MM/yy");
#Id
public Long id;
#Required
public String start_loc;
#Required
public String end_loc;
#Required
public String participant_type;
#Required
public String date = simpleDateFormat.format(new Date());
#Required
public String time = simpleTimeFormat.format(new Date());
#ManyToOne
public User createUser;
#ManyToOne
public User modifyUser;
public static Finder<Long,Journey> find = new Finder(
Long.class, Journey.class
);
public static List<Journey> all() {
return find.all();
}
public static void create(Journey journey) {
journey.save();
}
public static void delete(Long id) {
find.ref(id).delete();
}
public static List<Journey> searchByAddress(String address) {
return find.where().ilike("start_loc", "%"+address+"%").findList();
}
public void save() {
User logged = Application.getLocalUser(session());
if (logged != null) {
this.createUser = logged;
this.modifyUser = logged;
}
super.save();
}
public void update(Object o) {
User logged = Application.getLocalUser(session());
if (logged != null) {
this.modifyUser = logged;
}
super.update(o);
}
}
You don't need to write it manualy, for an example if you have a Book.java model you can add field for an example updatedBy to identify who was editing record last time, what's more you can override Model's methods save() and update(Object o) to make sure, that these fields will be always updated without additional effort.
#Entity
public class Book extends Model {
#Id
public Integer id;
#ManyToOne
public User createUser;
#ManyToOne
public User modifyUser;
public void save() {
User logged = Application.getLocalUser(session());
if (logged != null) {
this.createUser = logged;
this.modifyUser = logged;
}
super.save();
}
public void update(Object o) {
User logged = Application.getLocalUser(session());
if (logged != null) {
this.modifyUser = logged;
}
super.update(o);
}
// other fields/methods
}

Categories