I'd like to discuss contributing a solution to allowing UUID values for ObjectIdentity.getIdentifier() in spring-security-acl, SEC-972. The Spring Security Contributing guidelines point to Spring Security forums, which are now closed and point to Stack Overflow, so hopefully I'm asking in the right place.
My solution adds a new column to the acl_class table, class_id_type, that optionally allows you to specify the Java type for that acl_class. If you wire in a ConversionService to BasicLookupStrategy and the acl_class has a class_id_type specified, the ConversionService will be used to convert the identifier to the right type. This adds a dependency on spring-core.
The acl_class schema looks like this:
create table acl_class(
id bigint generated by default as identity(start with 100) not null primary key,
class varchar_ignorecase(100) not null,
class_id_type varchar_ignorecase(100),
constraint unique_uk_2 unique(class)
);
The definition of the lookupStrategy then looks like this:
<bean id="conversionService" class="org.springframework.context.support.ConversionServiceFactoryBean"/>
<!-- Declare a lookup strategy-->
<bean id="lookupStrategy" class="org.springframework.security.acls.jdbc.BasicLookupStrategy">
<constructor-arg ref="dataSource"/>
<constructor-arg ref="aclCache"/>
<constructor-arg ref="aclAuthorizationStrategy"/>
<constructor-arg ref="permissionGrantingStrategy"/>
<constructor-arg ref="conversionService"/>
<property name="permissionFactory" ref="permissionFactory"/>
</bean>
The tweaks to BasicLookupStrategy.convertCurrentResultIntoObject() look like this:
// If the Java type is a String, check to see if we can convert it to the target id type, e.g. UUID.
Serializable identifier = (Serializable) rs.getObject("object_id_identity");
if (isString(identifier) && hasValidClassIdType(rs)
&& canConvertFromStringTo(classIdTypeFrom(rs))) {
identifier = convertFromStringTo((String) identifier, classIdTypeFrom(rs));
}
ObjectIdentity objectIdentity = new ObjectIdentityImpl(rs.getString("class"),
identifier);
You can view the changes in a branch in this fork - https://github.com/pwheel/spring-security/tree/feature/acl-uuid-strings.
That branch contains some changes that are not relevant (e.g. private Maven repo) so please don't consider that branch a pull request in its own right. This change seems like a 'non-trivial' change so as per the contributing guidelines I'd like to discuss it before raising a pull request.
Note also that I found in my application I needed to implement a version of JdbcMutableAclService that uses the JdbcTemplate methods that take the SQL Types as arguments - this was because otherwise the MySQL connector maps UUID to binary rather than String, resulting in UTF-8 errors being thrown. I can add that to a pull request.
I am using this setup in production without any issues.
Are there any changes or improvements I should make before raising a pull request?
Thanks
Related
My environment is Grails 2.5.3 and I want to use redis cache. I have added
grails plugin spring-session:1.2 in Build.groovy
In resources.xml following is the redis related settings
<cache:annotation-driven proxy-target-class="true" />
<bean id="grailsCacheKeyGenerator" class="com.docu.commons.redis.GrailsCacheKeyGenerator"/>
<bean id="cacheManager" class="org.springframework.data.redis.cache.RedisCacheManager">
<constructor-arg ref="sessionRedisTemplate"/>
</bean>
Following is the code (in a component class) that generates error when I call the validation() method of the domain object, the error is - Method on class [com.docu.MemberInfo] was used outside of a Grails application.
#Component(memberAction)
Class MemberAction{
public void save(){
MemberInfo mi = new MemberInfo()
mi.properties = params
mi.validate()
}
}
What should I do. Note that if I remove the plugin spring-session:1.2 and the related settings from resource.xml file then my code works well.
Lets say I have a main component that I want to initialize in a specific way and I have it's constructor take an Interface for this purpose. Is there a way to define the implementation I want for this interface in my xml and in turn inject that into the main component as a parameter? Like this:
public interface IComponent2 {
void DoStuff();
}
public class ConcreteCompImpl2 : IComponent2 {
IComponent1 _comp;
public ConcreteCompImpl2(IComponent1 comp) {
_comp = comp;
}
public void DoStuff(){
//do stuff
}
}
<component id="component1" service="ABC.IComponent1, ABC" type="ABC.ConcreteCompImpl1, ABC" />
<component id="component2" service="ABC.IComponent2, ABC" type="ABC.ConcreteCompImpl2, ABC" >
<parameters>
<component1>???</component1>
</parameters>
</component>
Or am I thinking about this all wrong and there is a much simpler way to accomplish this? The main thing I want to be able to do is configure what 'kind' of IComponent1 will get injected whenever an IComponent2 is created. Thanks
If you have only one concrete class implementing IComponent1, then it will automatically be injected when you resolve IComponent2.
If you have several classes implementing IComponent1 and want a specific one every time IComponent2 is resolved, you need to specific an inline dependency:
container.Register(
Component.For<IComponent2>()
.ImplementedBy<Component2>()
.DependsOn(Dependency.OnComponent<IComponent1, YourSpecialComponent1>())
);
I'm not completely sure you can specify this in the XML configuration, but honestly you should use the Fluent API instead of the XML configuration unless you have a really compelling reason to use it. As mentioned in the above link:
Ability to register components in XML is mostly a leftover from early days of Windsor before Fluent Registration API was created. It is much less powerful than registration in code and many tasks can be only accomplished from code.
I am working on the project with Spring and Neo4j database. I configured my Neo4j database to be rest neo4j. This is the configuration:
<neo4j:config graphDatabaseService="graphDatabaseService" />
<bean id="graphDatabaseService" class="org.springframework.data.neo4j.rest.SpringRestGraphDatabase">
<constructor-arg index="0" value="http://localhost:7474/db/data" />
</bean>
At the beginning I was using notations on my domain objects (#NodeEntity, #RelatedTo, etc.) and repositories to save nodes and relationships. My domain objects are User(id, name), Item(id, name, description, list of terms), Term(content, count). So there not so many properties out there, but even so, saving the object through repository, for example a User with defined id and name lasted for 25 seconds.
I read that this kind of communication with neo4j database is not yet well optimized, so I switched on using the Neo4jTemplate.
This is a example of saving the user (constraints in User are Strings ("id", "name", "USER"):
public Node saveUser(User user) {
Node node = template.createNode();
node.setProperty(User.ID, user.getId());
node.setProperty(User.NAME, user.getName());
node.setProperty("_type", User.LABEL);
template.index(INDEX_ID, node, User.ID, user.getId());
return node;
}
And this is a example of saving the item with relationships to its terms. So each term is a node which is connected to the item:
public Node saveItem(Item item) {
Node node = template.createNode();
node.setProperty(Item.ID, item.getId());
node.setProperty(Item.NAME, item.getName());
node.setProperty(Item.DESCRIPTION, item.getDescription());
node.setProperty("_type", Item.LABEL);
template.index(INDEX_ID, node, Item.ID, item.getId());
for(String termContent : item.getTerms()) {
Node term = termRepository.getNodeByContent(termContent);
if(term == null) {
term = termRepository.saveTerm(new Term(termContent));
} else {
termRepository.addCountToTerm(term);
}
int frequency = 1;
Relationship contains = node.createRelationshipTo(term, RelationshipTypes.CONTAINS);
contains.setProperty(Term.FREQUENCY, frequency);
}
return node;
}
The object termRepository (it isn't extending GraphRespository<Term>) has methods which are similar to the method of saving the user. Fetching the term is done like this:
public Node getNodeByContent(String content) {
if(!template.getGraphDatabaseService().index().existsForNodes(INDEX_ID))
return null;
return template.lookup(INDEX_ID, Term.CONTENT, content).to(Node.class).singleOrNull();
}
And, finally what is my problem. Even now it is still slow, inserting user (only parameters id and name) and indexing it takes for 3 seconds, and inserting item where it is being connected to terms takes for 30 seconds (for 4 terms - which is very small ammount according to the number of 60-70 which I will have in real situation).
Please, can you give me some hint or anything else that could help me with this kind of issue?
Thanks in advance.
This is really strage, where does your server run? Seems to be something with the network setup.
I mean SDN over REST is not fast, but it is also not that slow.
Can you share your classes too?
You should not do the individual property updates over the wire. Use cypher statements that create all the properties in one go.
There is also neo4jTemplate.createNode(map of properties) which does it as one operation.
Simple question... quite possibly not simple answers :)
I want to write an accessibility service for android in monodroid. I'm finding it difficult to work out the pieces. I can inherit from AccessibilityService, but there isn't an AccessibilityServiceAttribute. I need specific content in the manifest file, but apparently the intent filter and service xml is not directly supported by monodroid... I believe.
I doubt this is something that many people have done, but as a beginner with Monodroid, I think I'm mainly just finding it difficult to put together the well supported "normal" app development, with the "supported" but not quite, accessibility service development.
I would appreciate any pointers. Thanks guys.
According to the docs:
An accessibility is declared as any other service in an AndroidManifest.xml but it must also specify that it handles the "android.accessibilityservice.AccessibilityService" Intent. Failure to declare this intent will cause the system to ignore the accessibility service.
Since it is declared the same way as any other service, you can make use of ServiceAttribute and IntentFilterAttribute to generate the entry in AndroidManifest.xml. For example:
[Service]
[IntentFilter(new[] { "android.accessibilityservice.AccessibilityService" })]
public class MyAccessibilityService : AccessibilityService
{
public override void OnAccessibilityEvent(AccessibilityEvent e)
{
}
public override void OnInterrupt()
{
}
}
When you build the application, Mono for Android will generate this in the manifest:
<service android:name="sample.MyAccessibilityService">
<intent-filter>
<action android:name="android.accessibilityservice.AccessibilityService" />
</intent-filter>
</service>
How do you handle primitive types when using a IoC container?
I.e. given that you have:
class Pinger {
private int timeout;
private string targetMachine;
public Pinger(int timeout, string targetMachine) {
this.timeout = timeout;
this.targetMachine = targetMachine;
}
public void CheckPing() {
...
}
}
How would you obtain the int and string constructor arguments?
Make another interface for this.
Then you will get something like:
public Pinger(IExtraConfiguration extraConfig)
{
timeout = extraconfig.TimeOut;
targetmachine = extraconfig.TargetMachine;
}
I don't know about other IOC containers, but Castle Windsor resolves these extra constructor parameters automatically.
I'm not sure if your difficulty is the value types or the concrete type. Neither is a problem. You don't need to introduce a configuration interface (it's useful if you want to pass the same parameters to multiple objects, but not in the case you've given). Anyway, here's the Windsor fluent code, I'm sure someone will submit an XML version soon.
container.Register(
Component.For(typeof(Pinger))
.ImplementedBy(typeof(Pinger)) // This might not be necessary
.Parameters(Parameter.ForKey("timeout").Eq("5000"),
Parameter.ForKey("targetMachine").Eq("machine")
)
);
It depends. The IoC-Container StructureMap will allow you to declare those dependencies when you configure the instance at the beginning of your execution.
e.g. in a registry
ForRequestedType<Pinger>()
.TheDefault.Is.OfConcreteType<Pinger>()
.WithCtorArg("timeout").EqualTo(5000)
.WithCtorArg("targetMachine").EqualToAppSetting("machine");
In Spring, one can look up property values from a property file using ${propertyName} notation
<bean class="blah.Pinger">
<constructor-arg value="${blah.timeout}"/>
<constructor-arg value="${blah.targetMachine}"/>
</bean>
In Spring.net the same functionality is provided by the PropertyPlaceholderConfigurer, which has the same syntax, and uses name value sections in config files.