How to override config value from #PropertySource used in a #ConfigurationProperties config class in a unit test using #TestPropertySource - unit-testing

I have a config properties instance with prefix "assets."
#Configuration
#ConfigurationProperties( prefix = "assets", ignoreUnknownFields = true )
public class AssetsProperties
{
#NotNull
private Resource file;
public Resource getFile()
{
return file;
}
public void setFile( Resource file )
{
this.file = file;
}
}
Its default configuration is defined in:
#Configuration
#PropertySource( name = "assetsConfig", value = "classpath:com/package/boot/web/ui/assets/config/default-assets-config.properties" )
#Order( LOW_ORDER )
public class AssetsConfig
{
}
default-assets-config.properties contains:
assets.file=classpath:assets.json
In my unit test I want to override the default value using:
#TestPropertySource( locations = "classpath:com/package/boot/web/ui/assets/tests/assets-config.properties" )
assets-config.properties contains
assets.file=classpath:com/package/boot/web/ui/assets/tests/assets.json
Unfortunately this value is never injected into AssetsProperties.
What do I do wrong, I don't understand because spring fmk ref doc says
Test property sources have higher precedence than those loaded from the operating system’s environment or Java system properties as well as property sources added by the application declaratively via #PropertySource or programmatically.
Thanks in advance,
Paskos

You've hit a limitation in Spring Boot which means that it ignores properties files configured using #TestPropertySource. As an alternative, you can configure one or more inlined properties instead:
#TestPropertySource(properties = "assets.file=classpath:com/package/boot/web/ui/assets/tests/assets.json")

Related

ServiceStack: Routes.AddFromAssembly still uses /json/reply path and no URL-niceness for properties

I have a ServiceStack self-hosted webservice, using the AppSelfHostBase.
WHen the Configure method is executed, I have this:
public override void Configure(Container container)
{
Config.RouteNamingConventions = new List<RouteNamingConventionDelegate> {
RouteNamingConvention.WithRequestDtoName,
RouteNamingConvention.WithMatchingAttributes,
RouteNamingConvention.WithMatchingPropertyNames,
};
Routes.AddFromAssembly(typeof(ServiceStackHost).Assembly);
and I expected the following service to be executed under /StartBankIdAuthentication path, but it resides under /json/reply/StartBankIdAuthentication instead.
public class StartBankIdAuthentication : IReturn<StartBankIdAuthenticationResponse>
{
public string IdNbr { get; set; }
}
Also, is there an automatic way to make the properties in the DTO to be under "sub-paths", like /StartBankIdAuthentication/1234 instead of the /StartBankIdAuthentication?IdNbr=1234?
I know I can manually add the Route attribute, but it seems cumbersome and also messy in many ways (not Typed, error-prone etc).
I expected the following service to be executed under /StartBankIdAuthentication path, but it resides under /json/reply/StartBankIdAuthentication instead.
The /json/reply/StartBankIdAuthentication is a pre-defined route that's always available by default, they have no relation to Auto Generated Routes.
The default Route generation strategies you've listed are already registered by default and are what's applied when you use Routes.AddFromAssembly(). You should only override with route strategies you want in addition to the defaults, and you should use SetConfig() for any configuration in ServiceStack, e.g:
SetConfig(new HostConfig {
RouteNamingConventions = { MyCustomRouteStrategy }
});
The implementation for the different Route Strategies available in ServiceStack are in RouteNamingConvention.cs, you'll need to register your own strategy for anything additional Route strategies you want.
By default additional routes are generated for any Id or IDs property, the routing docs shows examples of how they can be customized:
The existing rules can be further customized by modifying the related static properties, e.g:
RouteNamingConvention.PropertyNamesToMatch.Add("UniqueId");
RouteNamingConvention.AttributeNamesToMatch.Add("DefaultIdAttribute");
Which will make these request DTOs:
class MyRequest1
{
public UniqueId { get; set;}
}
class MyRequest2
{
[DefaultId]
public CustomId { get; set;}
}
Generate the following routes:
/myrequest1
/myrequest1/{UniqueId}
/myrequest2
/myrequest2/{CustomId}
I know I can manually add the Route attribute, but it seems cumbersome and also messy in many ways (not Typed, error-prone etc).
If you really want you can use nameof() for Typed Routes:
[Route("/" + nameof(StartBankAuthentication) +"/"+ nameof(StartBankAuthentication.IdNbr))]
I'm not sure if Mythz will maybe come up with a different of better solution, but I managed to achieve what I wanted by overriding the GetRouteAttributes, and by using reflection, I could create what I wanted. It looks like this:
public override RouteAttribute[] GetRouteAttributes(Type requestType)
{
string fullname = requestType.FullName.Replace("AlfaOnlineServiceModel.Api.", "");
string path = "/" + fullname.ToLower().Replace(".", "/");
RouteAttribute[] routes = base.GetRouteAttributes(requestType);
if (routes.Length == 0)
{
routes = new RouteAttribute[1];
PropertyInfo[] pInfos = requestType.GetProperties(System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.DeclaredOnly);
foreach(PropertyInfo pi in pInfos)
{
path += "/{" + pi.Name + "}";
}
routes[0] = new RouteAttribute(path);
}
return routes;
}
Which will give for example:
MyMethodResult
The following routes are available for this service:
All Verbs /myCoolPath/mySubPath/myMethod/{MyProperty}

How to attach Sitecore context for controller action mappled to route robots.txt?

In Sitecore I'm trying to set up a way for our client to modify the robots.txt file from the content tree. I am attempting to set up a MVC controller action that is mappled to route "robots.txt" and will return the file contents. My controller looks like this:
public class SeoController : BaseController
{
private readonly IContentService _contentService;
private readonly IPageContext _pageContext;
private readonly IRenderingContext _renderingContext;
public SeoController(IContentService contentService, IPageContext pageContext, IRenderingContext renderingContext, ISitecoreContext glassContext)
: base(glassContext)
{
_contentService = contentService;
_pageContext = pageContext;
_renderingContext = renderingContext;
}
public FileContentResult Robots()
{
string content = string.Empty;
var contentResponse = _contentService.GetRobotsTxtContent();
if (contentResponse.Success && contentResponse.ContentItem != null)
{
content = contentResponse.ContentItem.RobotsText;
}
return File(Encoding.UTF8.GetBytes(content), "text/plain");
}
}
And the route config:
public class RouteConfig
{
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
RouteTable.Routes.MapRoute("Robots.txt", "robots.txt", new { controller = "Seo", action = "Robots" });
}
}
This all works great if I use a route without the ".txt" extension. However after adding the extension I get a null reference exception in the domain layer due to the context database being null. Here's where the error happens:
public Item GetItem(string contentGuid)
{
return Sitecore.Context.Database.GetItem(contentGuid);
}
I'm assuming that there is a setting in sitecore that ignores the .txt extension. I've tried adding it as an allowed extension in the Sitecore.Pipelines.PreprocessRequest.FilterUrlExtensions setting of the config. Is there anything else I could be missing?
Ok, I found the issue. I was correct in assuming that txt needed to be added to the allowed extensions for the Sitecore.Pipelines.PreprocessRequest.FilterUrlExtensions setting. However robots.txt was listed under the IgnoreUrlPrefixes setting in the config file. That was causing sitecore to ignore that request. I removed it from that list and it's working great now.
This is a pure guess, but you might also have to add it to the allowed extensions of Sitecore.Pipelines.HttpRequest.FilterUrlExtensions in httpRequestBegin as well.

Using grails configuration values in domain object constraints

Grails 2.2.0
How do I access the custom configuration variables in a Grails domain object constraints.
I would like to have something like this:
class User {
def grailsApplication
String name
static constraints = {
name size: grailsApplication.config.maxlength
}
}
But it fails with "No such property: grailsApplication". I have tried to get it work by following suggestions in getting grails 2.0.0M1 config info in domain object, and static scope? but have not managed to get any combination to work.
How do I access config in domain object constraints? In addition how do I handle such a case in a unit test for the domain constraints?
You can use the grails.util.Holders class to get access to the configuration object as follows:
In Config.groovy:
myMaxSize = 10
In your domain class:
class User {
String name
static constraints = {
name minSize: Holders.config.myMaxSize
}
}

Can Pax Web Whiteboard ResourceMapping have path pointing outside the bundle?

I've tried to register the following ResourceMapping as an OSGi service:
package ru.focusmedia.odp.server.poim.http;
import org.ops4j.pax.web.extender.whiteboard.ResourceMapping;
import ru.focusmedia.odp.server.poim.api.PoimConfig;
import aQute.bnd.annotation.component.Component;
#Component(immediate = true)
public class PoimResourceMapping implements ResourceMapping {
private String httpContextId;
private String alias = "...";
private String someAbsolutePath = "...";
#Override
public String getHttpContextId() {
return httpContextId;
}
#Override
public String getAlias() {
return "/resources";
}
#Override
public String getPath() {
return someAbsolutePath;
}
}
but don't see the result in browser under http://127.0.0.1:8282/resources/aFileUnderMyPath. I can see that Pax Web is accessing my mapping in the log. Is this possible or do I need to write a servlet instead?
The short answer is no.
The path is resolved relative to the bundle and therefore your absolute path will turn in some url syntax error.
Why not loading your file in a bundle and serving it from there? We dynamically load bundles with resources that we need to serve following some versioning conventions.

Testing nhibernate Castle Windsor mappings in httpModules is not registered

I want to write test that verifies mappings in castle windsor.
I am using ASP MVC2 where i am using castle windsor to map my repositories.
I have read this article:
http://weblogs.asp.net/bsimser/archive/2008/06/04/the-first-spec-you-should-write-when-using-castle.aspx
and based on this i have created my MS Test
[TestMethod()]
public void GetContainerTest()
{
MooseMvc.Infrastructure.DependencyInjectionInitialiser target = new MooseMvc.Infrastructure.DependencyInjectionInitialiser(); // TODO: Initialize to an appropriate value
IWindsorContainer container = target.GetContainer();
foreach (IHandler assignableHandler in container.Kernel.GetAssignableHandlers(typeof(object)))
{
container.Resolve(assignableHandler.ComponentModel.Service);
}
}
The data for target.getcontainer() implements
this._windsorContainer.Register(Component.For<TInterfaceType>()
.ImplementedBy(typeof(TConcreteType)).LifeStyle.PerWebRequest);
I get message as follows:
Looks like you forgot to register the http module
Castle.MicroKernel.Lifestyle.PerWebRequestLifestyleModule Add '<add
name="PerRequestLifestyle"
type="Castle.MicroKernel.Lifestyle.PerWebRequestLifestyleModule,
Castle.Windsor" />' to the <httpModules> section on your web.config.
If you're running IIS7 in Integrated Mode you will need to add it to
<modules> section under <system.webServer>
I have had the same problem and I have found a solution: You can define an event in the contructor of the unit test to override the LifestyleType.
void Kernel_ComponentModelCreated(Castle.Core.ComponentModel model)
{
if (model.LifestyleType == LifestyleType.Undefined)
model.LifestyleType = LifestyleType.Transient;
if (model.LifestyleType == LifestyleType.PerWebRequest)
model.LifestyleType = LifestyleType.Transient;
}
public UnitTest1()
{
containerWithControllers = new WindsorContainer();
containerWithControllers.Kernel.ComponentModelCreated += new ComponentModelDelegate(Kernel_ComponentModelCreated);
}
i have found beautifull guide
http://docs.castleproject.org/Windsor.Windsor-tutorial-part-three-a-testing-your-first-installer.ashx
there is not much else to add..