I want to set the modifiedBy and createdBy properties of my DomainClasses automaticly.
For that i changed the Bootstrap.grooy to this:
import org.codehaus.groovy.grails.commons.GrailsDomainClass
class BootStrap {
def grailsApplication
def init = { servletContext ->
grailsApplication.domainClasses.each { GrailsDomainClass gdc ->
if (gdc.hasProperty('modifiedBy') && gdc.hasProperty('createdBy')) {
gdc.metaClass.beforeInsert = {
modifiedBy = springSecurityService.currentUser.id
createdBy = springSecurityService.currentUser.id
}
}
if (gdc.hasProperty('modifiedBy') && gdc.hasProperty('modified')) {
gdc.metaClass.beforeUpdate = {
modified = new Date()
modifiedBy = springSecurityService.currentUser.id
}
}
}
}
}
To get this work i need springSecurityService in all the DomainClasses that have the properties, I could add this:
def springSecurityService
static transients = ['springSecurityService']
How can i inject the springSecurityService without that?
I found a solution in this
This works with the Platform Plugin
Related
SonarQube ignores tests for AbstractValidators (FluentValidation.AspNetCore nuget package). In the coverage section, all RuleFor lines are marked as not covered.
What do I need to do, for the tests to be included in the coverage in SonarQube?
ReSharper shows the validator as being fully covered by tests.
The validator:
public class UserValidator : AbstractValidator<User>
{
public UserValidator()
{
RuleFor(a => a.Name).NotEmpty();
RuleFor(a => a.FirstName).NotEmpty();
}
}
Test class:
public class UserValidatorTests
{
[Test, TestCaseSource(nameof(User_InvalidData))]
public async Task ValidationShouldFail(UserAndErrors testData)
{
var result = await new UserValidator().TestValidateAsync(testData.User!);
Assert.IsFalse(result.IsValid);
Assert.AreEqual(result.Errors.Count, testData.ErrorsCount);
}
[Test]
public async Task ValidationShouldPass()
{
var request = new User
{
FirstName = "John",
Name= "Doe"
};
var result = await new UserValidator().TestValidateAsync(request);
Assert.IsTrue(result.IsValid);
result.ShouldNotHaveAnyValidationErrors();
}
private static IEnumerable<TestCaseData> User_InvalidData()
{
yield return new TestCaseData(new User
{
User = new User(),
ErrorsCount = 2
});
yield return new TestCaseData(new User
{
User = new User
{
Name = "Doe"
},
ErrorsCount = 1
});
yield return new TestCaseData(new User
{
User = new User
{
FirstName = "John"
},
ErrorsCount = 1
});
}
public class UserAndErrors
{
public User? User { get; set; }
public int ErrorsCount { get; set; } = 0;
}
}
User class:
public class User
{
public string Name { get; set; } = string.Empty;
public string FirstName { get; set; } = string.Empty;
}
The issue was the fact that the test project did not reference the coverlet.msbuild nuget package. Without it, SonarQube could not run the tests correctly and could not update the code coverage.
I'm new to Gradle (using 7.3.2) and currently trying to integrate org.openapi.generator's openApiGenerate task for all json OpenAPI template files of Amazon's selling partner API models from https://github.com/amzn/selling-partner-api-models.
plugins {
id 'org.ajoberstar.grgit' version '4.1.1'
id 'org.openapi.generator' version '5.3.0'
}
import org.ajoberstar.grgit.Grgit
project.ext.repoDirectory = "$buildDir/selling-partner-api-models"
project.ext.basePackage = "com.amazon.sellingpartner"
tasks.register('deleteRepo', Delete) {
delete project.ext.repoDirectory
}
class CloneSpapi extends DefaultTask {
#Input
String url = 'https://github.com/amzn/selling-partner-api-models.git'
#TaskAction
def clone() {
println 'Cloning Amazon Selling Partner OpenAPI from github ...'
def grgit = Grgit.clone(dir: project.ext.repoDirectory, uri: url)
grgit.close()
println 'done'
}
}
tasks.register('cloneSpapi', CloneSpapi) {
description 'Clones Amazon Selling Partner OpenAPI from github'
dependsOn tasks.named('deleteRepo')
}
interface GenerateParameters extends WorkParameters {
RegularFileProperty getJsonFile()
DirectoryProperty getOutputDir()
}
abstract class GenerateApi implements WorkAction<GenerateParameters> {
#Override
void execute() {
def file = parameters.jsonFile.get().getAsFile()
def modelName = file.getName().replace('.json', '')
println modelName + ": " + file
}
}
abstract class GenerateApis extends DefaultTask {
private final WorkerExecutor workerExecutor
#Input
abstract String directory = "$project.ext.repoDirectory/models"
#Inject
GenerateApis(WorkerExecutor workerExecutor) {
this.workerExecutor = workerExecutor
}
#TaskAction
void generateFiles() {
ConfigurableFileTree tree = project.fileTree(dir: directory)
tree.include '**/*.json'
Set<File> modelFiles = tree.getFiles().sort()
WorkQueue workQueue = workerExecutor.noIsolation()
modelFiles.each { File file ->
workQueue.submit(GenerateApi.class) { GenerateParameters parameters ->
parameters.jsonFile = file
}
}
}
}
tasks.register('generateApis', GenerateApis) {
}
openApiGenerate {
generatorName = "java"
inputSpec = // file
outputDir = "$buildDir/generated".toString()
invokerPackage = "$project.ext.basePackage"
apiPackage = "$project.ext.basePackage" + ".api.modelName" // modelName from
modelPackage = "$project.ext.basePackage" + ".model.modelName" // modelName here
configOptions = [
dateLibrary: "java8"
]
}
To simplify things, I have added a simple 'cloneSpapi' task to clone the repository.
gradle -q cloneSpapi
How do I call the openApiGenerate task for each template file?
I have now used the swagger.io library directly and was able to call the code generator directly.
buildscript {
repositories {
mavenCentral()
}
dependencies {
classpath("io.swagger:swagger-codegen:2.4.24")
}
}
plugins {
id 'org.ajoberstar.grgit' version '4.1.1'
}
import io.swagger.codegen.DefaultGenerator
import io.swagger.codegen.config.CodegenConfigurator
import org.ajoberstar.grgit.Grgit
project.ext.repoDirectory = "$buildDir/selling-partner-api-models"
project.ext.basePackage = "com.amazon.sellingpartner"
project.ext.outputDir = new File(project.buildDir, '/generated')
tasks.register('deleteRepo', Delete) {
delete project.ext.repoDirectory
}
class CloneSpapi extends DefaultTask {
#Input
String url = 'https://github.com/amzn/selling-partner-api-models.git'
#TaskAction
def clone() {
println 'Cloning Amazon Selling Partner OpenAPI from github ...'
def grgit = Grgit.clone(dir: project.ext.repoDirectory, uri: url)
grgit.close()
println 'done'
}
}
tasks.register('cloneSpapi', CloneSpapi) {
description 'Clones Amazon Selling Partner OpenAPI from github'
dependsOn tasks.named('deleteRepo')
}
interface GenerateParameters extends WorkParameters {
RegularFileProperty getJsonFile()
DirectoryProperty getTemplateDir()
DirectoryProperty getOutputDir()
Property<String> getBasePackage()
}
abstract class GenerateApi implements WorkAction<GenerateParameters> {
#Override
void execute() {
def file = parameters.jsonFile.get().getAsFile()
def modelName = file.getName().replace('.json', '')
println "Generating OpenAPI for $modelName"
def basePackage = parameters.basePackage.get()
def config = new CodegenConfigurator()
config.setInputSpec(file.toString()) // The swagger API file
config.setLang("java")
config.setTemplateDir(parameters.templateDir.get().toString())
config.setOutputDir(parameters.outputDir.get().toString()) // The output directory, user-service-contract/build/user-service-server/
config.setInvokerPackage(basePackage)
config.setApiPackage(basePackage + ".api." + modelName) // Package to be used for the API interfaces
config.setModelPackage(basePackage + ".model." + modelName) // Package to be used for the API models
config.setAdditionalProperties([
'dateLibrary' : 'java8', // Date library to use
'useTags' : 'true' // Use tags for the naming
])
def generator = new DefaultGenerator();
generator.opts(config.toClientOptInput());
generator.generate()
}
}
abstract class GenerateApis extends DefaultTask {
private final WorkerExecutor workerExecutor
#Input
abstract String directory = "$project.ext.repoDirectory/models"
#Inject
GenerateApis(WorkerExecutor workerExecutor) {
this.workerExecutor = workerExecutor
}
#TaskAction
void generate() {
ConfigurableFileTree tree = project.fileTree(dir: directory)
tree.include '**/*.json'
Set<File> modelFiles = tree.getFiles().sort()
WorkQueue workQueue = workerExecutor.noIsolation()
modelFiles.each { File file ->
workQueue.submit(GenerateApi.class) { GenerateParameters parameters ->
parameters.jsonFile = file
parameters.templateDir = new File(project.ext.repoDirectory, 'clients/sellingpartner-api-aa-java/resources/swagger-codegen/templates')
parameters.outputDir = project.ext.outputDir
parameters.basePackage = project.ext.basePackage
}
}
}
}
tasks.register('deleteGenerated', Delete) {
delete project.ext.outputDir
}
tasks.register('generateApis', GenerateApis) {
dependsOn tasks.named('deleteGenerated'), tasks.named('cloneSpapi')
}
My current Gradle configuration has multiple (Merged) res folders:
sourceSets {
androidTest {
setRoot('src/test')
}
main {
res.srcDirs =
[
'src/main/res/features/registration',
'src/main/res/features/login',
'src/main/res'
]
}
}
But Robolectric allows me to configure a single directory using AndroidManifest:
public class RobolectricGradleTestRunner extends RobolectricTestRunner {
private static final int MAX_SDK_SUPPORTED_BY_ROBOLECTRIC = 18;
public RobolectricGradleTestRunner(Class<?> testClass) throws InitializationError {
super(testClass);
}
#Override
protected AndroidManifest getAppManifest(Config config) {
String manifestProperty = "../app/src/main/AndroidManifest.xml";
String resProperty = "../app/src/main/res";
return new AndroidManifest(Fs.fileFromPath(manifestProperty), Fs.fileFromPath(resProperty)) {
#Override
public int getTargetSdkVersion() {
return MAX_SDK_SUPPORTED_BY_ROBOLECTRIC;
}
};
}
}
This way tests are failing. Is it possible to configure robolectric to reflect my gradle file?
Another solution similar to Luca's:
public class MyTestRunner extends RobolectricTestRunner {
...
#Override
protected AndroidManifest getAppManifest(Config config) {
String appRoot = "./src/main/";
String manifestPath = appRoot + "AndroidManifest.xml";
String resDir = appRoot + "res";
String assetsDir = appRoot + "assets";
return new AndroidManifest(Fs.fileFromPath(manifestPath), Fs.fileFromPath(resDir), Fs.fileFromPath(assetsDir)) {
#Override
public List<ResourcePath> getIncludedResourcePaths() {
List<ResourcePath> paths = super.getIncludedResourcePaths();
paths.add(new ResourcePath(getRClass(), getPackageName(), Fs.fileFromPath("../app/src/main/res/features/registration"), getAssetsDirectory()));
paths.add(new ResourcePath(getRClass(), getPackageName(), Fs.fileFromPath("../app/src/main/res/features/login"), getAssetsDirectory()));
return paths;
}
};
}
}
Don't forget to annotate your tests with #RunWith(MyTestRunner.class)
Ok, this is the easiest way to do it, You will have to extend RobolectricTestRunner getAppManifest and createAppResourceLoader.
In getAppManifest you will simply have to store the manifest in a field, let's say mDefaultManifest.
In createAppResourceLoader you will have to add the right resources injected.
/**
* TODO: Watch OUT this is copied from RobolectricTestRunner in Robolectric-2.4 keep it up to date!
*/
#Override
protected ResourceLoader createAppResourceLoader(ResourceLoader systemResourceLoader, AndroidManifest appManifest) {
List<PackageResourceLoader> appAndLibraryResourceLoaders = new ArrayList<PackageResourceLoader>();
for (ResourcePath resourcePath : appManifest.getIncludedResourcePaths()) {
appAndLibraryResourceLoaders.add(createResourceLoader(resourcePath));
}
/* BEGIN EDIT */
if(mDefaultManifest != null) {
ResourcePath rpInjected = new ResourcePath(mDefaultManifest.getRClass(), mDefaultManifest.getPackageName(), Fs.fileFromPath("../app/src/main/res/features/registration"), mDefaultManifest.getAssetsDirectory());
appAndLibraryResourceLoaders.add(createResourceLoader(rpInjected));
rpInjected = new ResourcePath(mDefaultManifest.getRClass(), mDefaultManifest.getPackageName(), Fs.fileFromPath("../app/src/main/res/features/login"), mDefaultManifest.getAssetsDirectory());
appAndLibraryResourceLoaders.add(createResourceLoader(rpInjected));
}
/* END EDIT */
OverlayResourceLoader overlayResourceLoader = new OverlayResourceLoader(appManifest.getPackageName(), appAndLibraryResourceLoaders);
Map<String, ResourceLoader> resourceLoaders = new HashMap<String, ResourceLoader>();
resourceLoaders.put("android", systemResourceLoader);
resourceLoaders.put(appManifest.getPackageName(), overlayResourceLoader);
return new RoutingResourceLoader(resourceLoaders);
}
Do not forget to add #RunWith(YourTestRunner.class) in your test classes.
ActionBase, ActionA, ActionB and ActionC are Entities (from a database). ActionA, ActionB and ActionC are derived type of ActionBase.
ActionB and ActionC implements ISpecialAction with a SpecialProperty.
ex :
public interface ISpecialAction
{
Guid SpecialProperty { get; }
}
public partial class ActionBase
{
public objectX OnePropertyBase { get; set; }
}
public partial class ActionA : ActionBase
{
public objectY OnePropertyA { get; set; }
}
public partial class ActionB:ActionBase,ISpecialAction
{
public objectZ OnePropertyB { get; set; }
public Guid SpecialProperty
{
get
{
return OnePropertyB.ID;
}
}
}
public partial class ActionC : ActionBase ,ISpecialAction
{
public objectW OnePropertyC { get; set; }
public Guid SpecialProperty
{
get
{
return OnePropertyC.ID;
}
}
}
My problem is that SpecialProperty is build from other Properties of the objects (ActionB or ActionC) and when the cast (to ISpecialAction) is done, OtherProperty and OtherProperty2 are null.
I tried :
GetActionBase().ToList().Where(x=>x is ISpecialAction && ((dynamic) x).SpecialProperty== p_SpecialProperty);
GetActionBase().ToList().Where(x=>x is ISpecialAction && ((ISpecialAction) x).SpecialProperty== p_SpecialProperty);
GetActionBase().ToList().OfType<ISpecialAction>().Where(x => x.SpecialProperty== p_SpecialProperty).Cast<ActionBase>();
return GetActionOnGoing().ToList().OfType<ICityAction>().Cast<ActionBase>().Where(x => ((dynamic)x).CityId == p_CityId);
remark : OfType<> doesn't works with an Interface in Linq to entities but is ok in Linq to object
How do I access my property interface without knowing the type of the object?
I might missed something but this is Ok with the code you provided :
public class objectX
{
}
public class objectY
{
}
public class objectZ
{
public Guid ID { get { return Guid.NewGuid();} }
}
public class objectW
{
public Guid ID { get { return new Guid(); } }
}
class Program
{
private static Guid p_SpecialProperty;
static void Main(string[] args)
{
var result = GetActionBase().ToList().Where(x => x is ISpecialAction && ((dynamic)x).SpecialProperty == p_SpecialProperty).FirstOrDefault();
var result1 = GetActionBase().ToList().Where(x => x is ISpecialAction && ((ISpecialAction)x).SpecialProperty == p_SpecialProperty).FirstOrDefault();
var result2 = GetActionBase().ToList().OfType<ISpecialAction>().Where(x => x.SpecialProperty == p_SpecialProperty).Cast<ActionBase>().FirstOrDefault();
}
private static IEnumerable<ActionBase> GetActionBase()
{
return new List<ActionBase> {new ActionA{OnePropertyA= new objectY()}, new ActionB{OnePropertyB=new objectZ()},new ActionC{OnePropertyC=new objectW()} };
}
}
Not sure if I exactly understand your question, but could you try using an intermediate interface, such as:
public interface ISpecialActionB : ISpecialAction
{
objectZ OnePropertyB { get; set; }
}
public class ActionB : ActionBase, ISpecialActionB
{
//same stuff
}
and casting to that instead.
var b = new ActionB{OnePropertyB = new Whatever()};
var bAsSpecial = b as ISpecialActionB;
var whatever = b.OnePropertyB; // should not be null
It' ok.
Your example run very well without problem so I searched in a other way : AutoMapper.
l_List.Actions = Mapper.Map<List<ActionBase>, Action[]>(l_ActionManagement.GetActionBySpecialId(l_Special.ID).ToList());
The problem was not interfaces or Linq queries but it was that automapper need an empty constructor and in this constructor, I need to initialize OnePropertyB and OnePropertyC to compute SpecialProperty.
Thanks
I created a local db with helper app project. and deployed it from isolate storage to installation folder,i added to project directory with content build action by add existing item. my problem is that i want to insert data, but i don't know how to move the db file to isolate storage to insert and data must add to my .sdf file that is locate in my project directory also.
Souphia,
While learning to use WP, I wrote a simple application that tracked tasks.
One version of that app stored all task data in Sql on the phone.
You can read the post and download all the code for the app here:
http://www.ritzcovan.com/2012/02/building-a-simple-windows-phone-app-part-3/
But, here is some of the code from that project:
First we have the model class decorated with the appropriate attributes:
[Table]
public class Task : INotifyPropertyChanged, INotifyPropertyChanging
{
[Column(IsDbGenerated = false, IsPrimaryKey = true, CanBeNull = false)]
public string Id
{
get { return _id; }
set
{
NotifyPropertyChanging("Id");
_id = value;
NotifyPropertyChanging("Id");
}
}
[Column]
public string Name
{
get { return _name; }
set
{
NotifyPropertyChanging("Name");
_name = value;
NotifyPropertyChanged("Name");
}
}
[Column]
public string Category
{
get { return _category; }
set
{
NotifyPropertyChanging("Category");
_category = value;
NotifyPropertyChanged("Category");
}
}
[Column]
public DateTime? DueDate
{
get { return _dueDate; }
set
{
NotifyPropertyChanging("DueDate");
_dueDate = value;
NotifyPropertyChanged("DueDate");
}
}
[Column]
public DateTime? CreateDate
{
get { return _createDate; }
set
{
NotifyPropertyChanging("CreateDate");
_createDate = value;
NotifyPropertyChanged("CreateDate");
}
}
[Column]
public bool IsComplete
{
get { return _isComplete; }
set
{
NotifyPropertyChanging("IsComplete");
_isComplete = value;
NotifyPropertyChanged("IsComplete");
}
}
[Column(IsVersion = true)] private Binary _version;
private string _id;
private bool _isComplete;
private DateTime? _createDate;
private DateTime? _dueDate;
private string _name;
private string _category;
public event PropertyChangedEventHandler PropertyChanged;
public event PropertyChangingEventHandler PropertyChanging;
public void NotifyPropertyChanged(string property)
{
if (PropertyChanged != null)
PropertyChanged(this, new PropertyChangedEventArgs(property));
}
public void NotifyPropertyChanging(string property)
{
if (PropertyChanging != null)
PropertyChanging(this, new PropertyChangingEventArgs(property));
}
}
In the constructor in app.xaml.cs, I have the following:
TaskMasterDataContext = new TaskMasterDataContext();
if (!TaskMasterDataContext.DatabaseExists())
{
TaskMasterDataContext.CreateDatabase();
DatabaseHelper.SetupDatabase(TaskMasterDataContext);
}
and here is the TaskMasterDataContext.cs code
public class TaskMasterDataContext : DataContext
{
public TaskMasterDataContext() : base("Data Source=isostore:/TaskMasterData.sdf")
{
}
public Table<Task> Tasks;
}
public static class DatabaseHelper
{
public static void SetupDatabase(TaskMasterDataContext dataContext)
{
string category = string.Empty;
var tasks = new List<Task>();
for (int i = 0; i < 20; i++)
{
tasks.Add(new Task()
{
Id = System.Guid.NewGuid().ToString(),
Category = GetCategoryString(i),
CreateDate = DateTime.Now,
DueDate = DateTime.Now.AddDays(new Random().Next(1, 30)),
IsComplete = false,
Name = String.Format("{0} Task # {1}", GetCategoryString(i), i)
});
}
dataContext.Tasks.InsertAllOnSubmit(tasks);
dataContext.SubmitChanges();
}
private static string GetCategoryString(int i)
{
if (i%2 == 0)
return "home";
if (i%3 == 0)
return "personal";
return "work";
}
}
The DatabaseHelper class is just there to populate the DB with some test data after its created.
I hope this helps.