Specific behaviour on validate() method on Play! Framework - forms

I am looking to have specific behaviour on my validate() method (like the one I can have with the groups annotation) either if it's called on
Form<User> loginForm = form(User.class, User.Login.class).bindFromRequest();`
or on
Form<User> registerForm = form(User.class, User.Register.class).bindFromRequest();
User Model :
#Entity
public class User extends Model {
public interface Register {}
public interface Login{}
#Required(groups = {Register.class, Login.class})
public String username;
#Required(groups = {Register.class, Login.class})
public String password;
public List<ValidationError> validate() {
... // Here I would like to distinguish User.Login.class from User.Register.class
}
}
Application Controller
public static Result loginSubmit(){
Form<User> loginForm = form(User.class, User.Login.class).bindFromRequest();
}
public static Result registerSubmit(){
Form<User> registerForm = form(User.class, User.Register.class).bindFromRequest();
}

The group parameter isn't passed to the validate() method so I don't think that's possible. It's not as convenient but you could just call validate (or some other validation method) yourself.
User Model:
public class User extends Model
{
public List<ValidationError> validate(Class group) {
if (group == Login.class) {
...
} else if (group == Register.class) {
...
}
}
}
Controller:
public static Result loginSubmit(){
Form<User> loginForm = form(User.class, User.Login.class).bindFromRequest();
if (!loginForm.hasErrors()) {
User user = loginForm.get();
List<ValidationError> errors = user.validate(User.Login.class);
...
}
}

Related

With LightInject, how can I pass arguments to child dependencies without registering a bunch of factories?

In the code below, I am trying to inject a ViewModel into a View, while the ViewModel requires a Model to wrap and another service that is in the container. The Model is not registered as it is not really a "service".
How do I:
a) not have to provide the IService instance as an argument (let the container resolve it),
b) not have to register a factory for my ViewModels (there will be many)
So what I'm really asking the container to do is treat my Model (that I pass as an argument) as if it were a registered "service" for the duration of this call to GetInstance.
If this is not possible with LightInject, are there any containers out there that have something like this?
public static class Program
{
public static void Main()
{
var container = new LightInject.ServiceContainer();
var service = new Service1();
container.RegisterInstance<IService>(service);
// Have to register the factory
container.Register<IService, PersonModel, PersonViewModel>(
(f, s, p) => new PersonViewModel(s, p));
container.Register<View>();
var person = new PersonModel(); // this is contextual -- not a service.
object view = CreateView(container, typeof(View), service, person);
// ultimate desired code:
//var view = container.GetInstance(typeof(View), new object[] { person });
}
private static object CreateView(ServiceContainer container, Type viewType, IService service, object model)
{
var ctor = viewType.GetConstructors()[0];
var parameters = new List<object>();
foreach (var param in ctor.GetParameters())
{
var attr = param.GetCustomAttributes(typeof(ModelAttribute), false).FirstOrDefault();
if (model != null && attr != null)
{
parameters.Add(model);
}
else
{
parameters.Add(container.GetInstance(param.ParameterType, new object[] { service, model }));
}
}
return Activator.CreateInstance(viewType, parameters.ToArray());
}
}
public interface IService
{
}
public class Service1 : IService
{
}
public class PersonModel
{
}
public class PersonViewModel
{
public PersonModel PersonModel { get; set; }
public PersonViewModel(IService service, [Model] PersonModel person)
{
PersonModel = person;
}
}
public class View
{
public PersonViewModel PersonViewModel { get; set; }
public View(PersonViewModel vm)
{
PersonViewModel = vm;
}
}
[AttributeUsage(AttributeTargets.Parameter, AllowMultiple = false, Inherited = false)]
public class ModelAttribute : Attribute
{
}
I have solved the issues with a combination of techniques...
a) use a Scope and register the ViewModel and View with PerScopeLifetime.
b) use a "ModelTracker" registered with a factory to allow an instance not created by the container to be injected (since models will be created by client code or a DbContext).
This combination also allows me to not register a factory for every ViewModel type -- but instead use the built-in mass registration functions (like RegisterAssembly).
public static class Program
{
public static void Main()
{
var container = new LightInject.ServiceContainer();
container.RegisterInstance<IService>(new Service1());
container.Register<View>(new PerScopeLifetime());
container.Register<PersonViewModel>(new PerScopeLifetime());
container.Register<ModelTracker>(new PerScopeLifetime());
container.Register<PersonModel>((f) => (PersonModel)f.GetInstance<ModelTracker>().Instance);
using (var scope = container.BeginScope())
{
var tracker = scope.GetInstance<ModelTracker>();
tracker.Instance = new PersonModel() { Name = "person1" };
var view = scope.GetInstance<View>();
}
}
}
public class ModelTracker
{
public object Instance { get; set; }
}
public class PersonModel
{
public string Name { get; set; }
}
public class PersonViewModel
{
private readonly IService service;
private readonly PersonModel person;
public PersonViewModel(IService service, PersonModel person)
{
this.service = service;
this.person = person;
}
}
public class View
{
public PersonViewModel PersonViewModel { get; set; }
public View(PersonViewModel vm)
{
PersonViewModel = vm;
}
}
public interface IService { }
public class Service1 : IService { }

How to pass parameters in dagger2?

Like the following:
public class MainActivity extends Activity {
#Inject
User mUser1;
#Inject
User mUser2;
#Inject
User mUser3;
protected void onCreate(#Nullable Bundle savedInstanceState) {
// how to inject ...
......
Log.d("XXX",mUser1.getName());
Log.d("XXX",mUser2.getName());
Log.d("XXX",mUser3.getName());
}
}
public class User {
private final String name;
public User (String name) {
this.name = name;
}
public String getName() {
return name;
}
}
#Module
public class MainModule {
#Provides
User providesUser(String name) {
return new User(name);
}
#Provides
String providesUser() {
return "Jack";
}
}
#Component(modules = MainModule .class)
public interface ChildComponent {
void inject(MainActivity activity);
}
Above the code, only create three user object with same name, but i want to created with diff name
I try to use '#Qualifier', but it only distinguish constructor, can't transfer the name parameter
I try this in MainModule.java:
#Named("Yuri")
#Provides
User providesUser() {
return new User("yuri");
}
#Named("Warren")
#Provides
User providesUser() {
return new User("warren");
}
#Named("Jack")
#Provides
User providesUser() {
return new User("Jack");
}
But the method 'providesUser' is already defined.
Name parameter is final, can't modify
How should this situation be handled!!!
Method name doesn't matter. Only return type is what matters. So:
#Named("Yuri")
#Provides
User providesUserYuri() {
return new User("yuri");
}
#Named("Warren")
#Provides
User providesUserWarren() {
return new User("warren");
}
#Named("Jack")
#Provides
User providesUserJack() {
return new User("Jack");
}
If you want a dynamic name association, don't use #Qualifier, these are just for make differential of #Providers parameters.
Simply use Java POJO objects.
Now the User class would be like this:
public class User {
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
Now in your Activity you can say this:
#Override
protected void onPostCreate(#Nullable Bundle savedInstanceState) {
super.onPostCreate(savedInstanceState);
user1.setName("Ali");
user2.setName("Hossein");
user3.setName("Reza");
Log.d(TAG, user1.getName());
Log.d(TAG, user2.getName());
Log.d(TAG, user3.getName());
}

How to Create Lookup by Account Type using DimensionDynamicAccountController?

I have a problem.
I have in my new table two new fields
1) Name -> AccountNum, EDT--> DimensionDynamicAccount
2) Name -> AccountType, EDT--> LedgerJournalACType
class declaration
:
public class FormRun extends ObjectRun
{
DimensionDynamicAccountController dimAccountController;
}
init (for the form):
public void init()
{
super();
dimAccountController = DimensionDynamicAccountController::construct(
MyTable_ds,
fieldstr(MyTable, LedgerDimension),
fieldstr(MyTable, AccountType));
}
4. Override the following methods on the Segmented Entry control instance in the form design.
public void jumpRef()
{
dimAccountController.jumpRef();
}
public void loadAutoCompleteData(LoadAutoCompleteDataEventArgs _e)
{
super(_e);
dimAccountController.loadAutoCompleteData(_e);
}
public void segmentValueChanged(SegmentValueChangedEventArgs _e)
{
super(_e);
dimAccountController.segmentValueChanged(_e);
}
public void loadSegments()
{
super();
dimAccountController.parmControl(this);
dimAccountController.loadSegments();
}
public boolean validate()
{
boolean isValid;
isValid = super();
isValid = dimAccountController.validate() && isValid;
return isValid;
}
5. Override the following methods on the data source field that backs the Segmented Entry control.
public Common resolveReference(FormReferenceControl _formReferenceControl)
{
return dimAccountController.resolveReference();
}
Now my problem is Lookup only works for AccountType=="Ledger" not for customer, Vendor etc...
If I have a AccountType == Vendor or similant but different to Ledger I see this
I would want to have same the same thing that's in the LedgerJournalTrans Form
There is a solution,
thanks all,
enjoy
This might be too obvious, but I think you're missing the lookup() method.
See:
\Forms\LedgerJournalTransDaily\Designs\Design\[Tab:Tab]\[TabPage:OverViewTab]\[Grid:overviewGrid]\SegmentedEntry:LedgerJournalTrans_AccountNum\Methods\lookup
public void lookup()
{
if (!ledgerJournalEngine.accountNumLookup(ledgerJournalTrans_AccountNum,
ledgerJournalTrans,
ledgerJournalTrans.OffsetAccountType,
ledgerJournalTrans.parmOffsetAccount(),
ledgerJournalTrans_Asset))
{
super();
}
}

How can I achieve the following using IOC?

I want to use IOC with my service and I want to instead inject a class not an interface in the constructor as below in the services layer but I do not want to create a new object from the calling layer like var service = new InvoiceService(new ChangeInvoiceDueDateCommand()) instead I want to create something like this from my controller in MVC where the IInvoiceService is injected into the controller constructor but the problem I see is that
public InvoiceController(IInvoiceService invoiceService, IMapper mapper)
{
_invoiceService = invoiceService;
_mapper = mapper;
}
and then called like this
public ActionResult ChangeInvoiceDueDate(InvoiceChangeDueDateViewModel invoiceChangeDueDateViewModel )
{
var request = _mapper.Map<InvoiceChangeDueDateViewModel, ChangeInvoiceDuedateRequest>(invoiceChangeDueDateViewModel);
InvoiceChangeDueDateResponse response = _invoiceService.ChangeDueDate(request);
return View();
}
Service Layer
public class InvoiceService : IInvoiceService
{
private readonly ChangeInvoiceDueDateCommand _changeInvoiceDueDateCommand;
public InvoiceService(ChangeInvoiceDueDateCommand changeInvoiceDueDateCommand)
{
_changeInvoiceDueDateCommand = changeInvoiceDueDateCommand;
}
public InvoiceChangeDueDateResponse ChangeDueDate(ChangeInvoiceDuedateRequest invoiceChangeDueDateRequest)
{
_changeInvoiceDueDateCommand.Execute(invoiceChangeDueDateRequest);
return new InvoiceChangeDueDateResponse {Status = new Status()};
}
}
Command
public class ChangeInvoiceDueDateCommand : ICommand<ChangeInvoiceDuedateRequest>
{
private readonly IRepository<Invoice> _invoiceRepository;
readonly InvoiceDueDateChangeValidator _validator;
public ChangeInvoiceDueDateCommand(IRepository<Invoice> invoiceRepository)
{
_invoiceRepository = invoiceRepository;
_validator = new InvoiceDueDateChangeValidator();
}
public void Execute(ChangeInvoiceDuedateRequest request)
{
if (_validator.IsDuedateValid(request.NewDuedate))
{
Invoice invoice = _invoiceRepository.GetById(request.Id);
invoice.ChangedDueDate(request.NewDuedate);
_invoiceRepository.SaveOrUpdate(invoice);
}
else
{
throw new InvalidDueDateException();
}
}
}
ICommand
public interface ICommand<T> where T : IRequest
{
void Execute(T request);
}
IRequest
public interface IRequest
{
int Id { get; set; }
}
I worked it out. It was just a Windsor syntax issue. It ended up being as simple as registering the Command using the container.Register(Component.For<ChangeInvoiceDueDateCommand>());

how to reference controller function from another controller

Trying to learn ASP MVC coming from Linux/LAMP background (in other words I'm a newb) ...
For some reason I can't seem to use a function defined in a controller in another controller.
Here's the function in my MessagesController.cs file:
public List<Message> GetMessagesById(string username)
{
return db.Messages.Where(p => p.user == username).ToList();
}
When I try to reference it:
using LemonadeTrader.Models;
using LemonadeTrader.Controllers; // added this to pull the Messages::getMesssagesById
...
ViewBag.messages = lemondb.Messages.GetMessagesById(Membership.GetUser().ProviderUserKey.ToString());
I get something along the lines of lemondb.Messages does not contain a method called GetMesssagesById.
How do I reference it?
You shouldn't be linking controller methods like this, not to mention that controllers shouldn't be performing data access directly. I would recommend you externalizing this function into a separate class/repository which could be used by both controllers.
Example:
public class MessagesRepository
{
public List<Message> GetMessagesById(string username)
{
return db.Messages.Where(p => p.user == username).ToList();
}
}
and then:
public class FooController: Controller
{
public ActionResult Index()
{
var db = new MessagesRepository()
ViewBag.messages = db.GetMessagesById(Membership.GetUser().ProviderUserKey.ToString());
return View();
}
}
public class BarController: Controller
{
public ActionResult Index()
{
var db = new MessagesRepository()
ViewBag.messages = db.GetMessagesById(Membership.GetUser().ProviderUserKey.ToString());
return View();
}
}
OK, that's the first step. This code could be improved by decoupling the controllers from the repository by introducing an abstraction for this repository:
public interface IMessagesRepository
{
List<Message> GetMessagesById(string username);
}
public class MessagesRepository: IMessagesRepository
{
public List<Message> GetMessagesById(string username)
{
return db.Messages.Where(p => p.user == username).ToList();
}
}
then you could use constructor injection for those controllers:
public class FooController: Controller
{
private readonly IMessagesRepository _repository;
public class FooController(IMessagesRepository repository)
{
_repository = repository;
}
public ActionResult Index()
{
ViewBag.messages = _repository.GetMessagesById(Membership.GetUser().ProviderUserKey.ToString());
return View();
}
}
public class BarController: Controller
{
private readonly IMessagesRepository _repository;
public class BarController(IMessagesRepository repository)
{
_repository = repository;
}
public ActionResult Index()
{
ViewBag.messages = _repository.GetMessagesById(Membership.GetUser().ProviderUserKey.ToString());
return View();
}
}
finally you would configure your DI framework to pass the corresponding implementation into those controllers.
I would also recommend you replacing this ViewBag with a strongly typed view model:
public class MyViewModel
{
public List<Message> Messages { get; set; }
}
and then:
public ActionResult Index()
{
var model = new MyViewModel
{
Messages = _repository.GetMessagesById(Membership.GetUser().ProviderUserKey.ToString())
};
return View(model);
}
Place GetMessageById (and all other methods needed for accessing messages) to separate class and use the class everywhere you need to get Message data.
MessageService service = new MessageService();
ViewBag.messages = service.GetMessagesById(...);