There seems be some things missing in the Spring-LDAP ODM annotations. This is a question by way of a feature request, if there is a better way to contribute such requests, please say so.
I'd like to mark an #Attribute as read-only, so it will populate the bean from LDAP for reference, but not persist it back to ldap. I'd suggest adding an attribute read-only to #Attribute, defaulting to false, for the usual case. The default attributes of * misses all the operational attributes, some of which are very useful, and transfers more data than is required, slowing down the ldap query with attributes which will never be used.
An example of this; it would be very useful, for literally read only, such as entryUUID, etag, etc., which you cannot use if you wish to persist only some fields back to ldap, as the bean fails to persist to ldap with an exception when you save the bean. But also would be usefule for general fields which you want to structurally prevent the user from ever updating.
You can get around this by not annotating read-only fields, and then manually populating the read only fields with a separate call. Very messy and kills the query speed.
Also on a related topic, query() coudl have a default list of attributes, which you have already annotated in your classes, something like :
public static String[] getBeanAttributes(Class<?> beanClass) {
ArrayList<String> attrsObj = new ArrayList<>();
for (Field field : beanClass.getDeclaredFields()) {
if (field.isAnnotationPresent(Attribute.class)) {
Attribute attr = field.getAnnotation(Attribute.class);
attrsObj.add(attr.name());
}
}
String[] attrs = attrsObj.toArray(new String[attrsObj.size()]);
return attrs;
}
Above just returns a simple String[] of your declared attributes, to pass to query.attributes() - now i realize that as a static member, query() is built before the bean class is known, but at least there could be a helper function like the above, or a method signature for query attributes() that took a bean Class signature as an argument.
I created LDAP-312 on Jira. Thanks.
Related
Using Room and RxJava3, my DAO interfaces always have methods with different return types (Maybe and Flowable) but with the exact same query. This is how I solve an important issue, which is that whenever I use Flowables, I want an empty list emitted immediately when the table is empty (rather than nothing at all).
Duplicating the query string may introduce bugs if I ever get sloppy and forget to update all of them. Now that I found I can still get syntax highlighting in Android Studio when storing the query, I came up with the following.
String query = "SELECT * FROM MyObject"; // public, as DAO is a public java interface
#Query(query)
Maybe<List<MyObject>> maybeMyObjectList();
#Query(query)
Flowable<List<MyObject>> flowableMyObjectList();
This enables me to do things like flowableMyObjectList().startWith(maybeMyObjectList().defaultIfEmpty(Collections.emptyList())).distinctUntilChanged()
Still, having SQL queries stored in a public string feels like a bad idea, security-wise. On the other hand, I don't think the database schema in my app bundle is supposed to be secret anyway. Can anyone with a better knowledge than mine confirm that it is a bad as it sounds, or better propose a workaround?
Instead of an interface you can use an abstract class, thus you can then have methods with bodies and private variables.
You then have to make the methods abstract.
So you could have:-
#Dao
abstract class TheDao {
private static final String query = "SELECT * FROM MyObject";
#Query(query)
abstract Maybe<List<MyObject>> maybeMyObjectList();
#Query(query)
abstract Flowable<List<MyObject>> flowableMyObjectList();
}
Is there a way we can use ObjectContext with DbContext's ModelBuilder? We don't want to use POCO because we have customized property code that does not modify entire object in update, but only update modified properties. Also we have lots of serialisation and auditing code that uses EntityObject.
Since poco does create a proxy with EntityObject, we want our classes to be derived from EntityObject. We don't want proxy. We also heavily use CreateSourceQuery. The only problem is EDMX file and its big connection string syntax web.config.
Is there any way I can get rid of EDMX file? It will be useful as we can dynamically compile new class based on reverse engineering database.
I would also like to use DbContext with EntityObject instead of poco.
Internal Logic
Access Modified Properties in Save Changes which is available in ObjectStateEntry and Save them onto Audit with Old and New Values
Most of times we need to only check for Any condition on Navigation Property for example
User.EmailAddresses.CreateSourceQuery()
.Any( x=> x.EmailAddress == givenAddress);
Access Property Attributes, such as XmlIgnore etc, we rely heavily on attributes defined on the properties.
A proxy for a POCO is a dynamically created class which derives from (inherits) a POCO. It adds functionality previously found in EntityObject, namely lazy loading and change tracking, as long as a POCO meets requirements. A POCO or its proxy does not contain an EntityObject as the question suggests, but rather a proxy contains functionality of EntityObject. You cannot (AFAIK) use ModelBuilder with EntityObject derivatives and you cannot get to an underlying EntityObject from a POCO or a proxy, since there isn't one as such.
I don't know what features of ObjectContext does your existing serialisation and auditing code use, but you can get to ObjectContext from a DbContext by casting a DbContext to a IObjectContextAdapter and accessing IObjectContextAdapter.ObjectContext property.
EDIT:
1. Access Modified Properties in Save Changes which is available in ObjectStateEntry and Save them onto Audit with Old and New Values
You can achieve this with POCOs by using DbContext.ChangeTracker. First you call DbContext.ChangeTracker.DetectChanges to detect the changes (if you use proxies this is not needed, but can't hurt) and then you use DbCotnext.Entries.Where(e => e.State != EntityState.Unchanged && e.State != EntityState.Detached) to get DbEntityEntry list of changed entities for auditing. Each DbEntityEntry has OriginalValues and CurrentValues and the actual Entity is in property Entity.
You also have access to ObjectStateEntry, see below.
2. Most of times we need to only check for Any condition on Navigation Property for example:
User.EmailAddresses.CreateSourceQuery().Any( x=> x.EmailAddress == givenAddress);
You can use CreateSourceQuery() with DbContext by utilizing IObjectContextAdapter as described previously. When you have ObjectContext you can get to the source query for a related end like this:
public static class DbContextUtils
{
public static ObjectQuery<TMember> CreateSourceQuery<TEntity, TMember>(this IObjectContextAdapter adapter, TEntity entity, Expression<Func<TEntity, ICollection<TMember>>> memberSelector) where TMember : class
{
var objectStateManager = adapter.ObjectContext.ObjectStateManager;
var objectStateEntry = objectStateManager.GetObjectStateEntry(entity);
var relationshipManager = objectStateManager.GetRelationshipManager(entity);
var entityType = (EntityType)objectStateEntry.EntitySet.ElementType;
var navigationProperty = entityType.NavigationProperties[(memberSelector.Body as MemberExpression).Member.Name];
var relatedEnd = relationshipManager.GetRelatedEnd(navigationProperty.RelationshipType.FullName, navigationProperty.ToEndMember.Name);
return ((EntityCollection<TMember>)relatedEnd).CreateSourceQuery();
}
}
This method uses no dynamic code and is strongly typed since it uses expressions. You use it like this:
myDbContext.CreateSourceQuery(invoice, i => i.details);
I have used many JSON object in applicationScope, sessionScope, and viewScope to track related data. Writing and reading these in SSJS is very simple:`
//Create a app scope variable
applicationScope.put("myvarname", {p1:"part 1", p2:"part2"});
// read and use the app scope variable ...
var myvar = applicationScope.get("myvarname");
//Work with parts as myvar.p1, myvar.p2, etc...
In the Java code I have been writing I have learned to read these variables which were written using SSJS using the com.ibm.jscript.std.ObjectObject package with code like this:
ObjectObject myvar = (ObjectObject) ExtLibUtil
.getApplicationScope().get(dbkey);
FBSValue localFBS = myvar.get("p1");
String myp1 = localFBS.stringValue();
localFBS = myvar.get("p2");
String myp2 = localFBS.stringValue();
Now, of course, I want to write a new entry using the Java Bean that can then be read by SSJS and other Java Beans in the same manner. I managed to write to the scope using a Map and a Hashtable, but these crash the logic when trying to read using the ObjectObject.
So, how would I go about building a new entry in the scope using the ObjectObject and/or FBSValue packages? I cannot find how to create a new FBSValue that can then be added to an ObjectObject. I am sure it is a simple thing a Newbs like me has missed.
/Newbs
You can construct an empty ObjectObject, populate it with FBSValues, and just put it directly into the scope Map:
ObjectObject myvar = new ObjectObject();
try {
myvar.put("p1", FBSUtility.wrap("part 1"));
myvar.put("p2", FBSUtility.wrap("part 2"));
} catch (InterpretException e) {
e.printStackTrace();
}
Map<String, Object> applicationScope = ExtLibUtil.getApplicationScope();
applicationScope.put("myvarname", myvar);
When retrieving it later (as in the examples you provided), SSJS will see it as JSON, Java will see it exactly as it was stored.
If you need to store deeper hierarchies, you can put instances of ArrayObject and ObjectObject inside an ObjectObject in addition to primitives, so, just like JSON itself, you can nest these as deep as you need.
Just be sure to only include true JSON (strings, numbers, booleans, arrays, objects) if you'll be storing it anywhere higher than the requestScope; specifically, FunctionObject does not implement Serializable, so JSON is safe to store, JavaScript is not. Strictly speaking, this only becomes toxic when stored in the viewScope in 8.5.2 and 8.5.3 (and even then, only when the application's persistence option is not set to keep all pages in memory). But if IBM ever implements cluster support, then all objects stored in sessionScope and applicationScope will need to be serializable to allow for inter-server state transport... so, in the interest of future-proofing the design, it's wise to hold to this principle for anything stored longer than the duration of a single request.
After the previous question "What are the important rules in Object Model Design", now I want to ask this:
Is there any way to have dynamic properties for class instances?
Suppose that we have this schematic object model:
So, each object could have lots of properties due to the set of implemented Interfaces, and then become relatively heavy object. Creating all the possible -and of course reasonable- object can be a way for solving this problem (i.e. Pipe_Designed v.s. Pipe_Designed_NeedInspection), but I have a large number of interfaces by now, that make it difficult.
I wonder if there is a way to have dynamic properties, something like the following dialog to allow the end user to select available functionalities for his/hers new object.
What you want is Properties pattern. Check out long and boring but clever article from Steve Yegge on this
I think maybe you're putting too many roles into the "Road" and "Pipe" classes, because your need for dynamic properties seems to derive from various states/phases of the artifacts in your model. I would consider making an explicit model using associations to different classes instead of putting everything in the "Road" or "Pipe" class using interfaces.
If you mean the number of public properties, use explicit interface implementation.
If you mean fields (and object space for sparse objects): you can always use a property bag for the property implementation.
For a C# example:
string IDesigned.ApprovedBy {
get {return GetValue<string>("ApprovedBy");}
set {SetValue("ApprovedBy", value);}
}
with a dictionary for the values:
readonly Dictionary<string, object> propValues =
new Dictionary<string, object>();
protected T GetValue<T>(string name)
{
object val;
if(!propValues.TryGetValue(name, out val)) return default(T);
return (T)val;
}
protected void SetValue<T>(string name, T value)
{
propValues[name] = value;
}
Note that SetValue would also be a good place for any notifications - for example, INotifyPropertyChanged in .NET to implement the observer pattern. Many other architectures have something similar. You can do the same with object keys (like how EventHandlerList works), but string keys are simpler to understand ;-p
This only then takes as much space as the properties that are actively being used.
A final option is to encapsulate the various facets;
class Foo {
public bool IsDesigned {get {return Design != null;}}
public IDesigned Design {get;set;}
// etc
}
Here Foo doesn't implement any of the interfaces, but provides access to them as properties.
If you have a class with some plain get/set properties, is there any reason to use the getters within the class methods, or should you just use the private member variables? I think there could be more of an argument over setters (validation logic?), but I'm wondering just about getters.
For example (in Java) - is there any reason to use option 2?:
public class Something
{
private int messageId;
public int getMessageId() { return this.messageId; }
public void setMessage(int messageId) { this.messageId = messageId; }
public void doSomething()
{
// Option 1:
doSomethingWithMessageId(messageId);
// Option 2:
doSomethingWithMessageId(getMessageId());
}
}
Java programmers in general tend to be very consistent about using getter methods. I program multiple languages and I'm not that consistent about it ;)
I'd say as long as you don't make a getter it's ok to use the raw variable - for private variables. When you make a getter, you should be using only that. When I make a getter for a private field, my IDE suggests that it replace raw field accesses for me automatically when I introduce a getter. Switching to using a getter is only a few keystrokes away (and without any chance of introducing errors), so I tend to delay it until I need it.
Of course, if you want to stuff like getter-injection, some types of proxying and subclassing framworks like hibernate, you have to user getters!
With getters you wont accidentally modify the variables :) Also, if you use both getters and the "raw" variable, your code can get confused.
Also, if you use inheritance and redefined the getter methods in child classes, getter-using methods will work properly, whereas those using the raw variables would not.
If you use the getter method everywhere - and in the future perform a code-search on all calls of getMessageId() you will find all of them, whereas if you had used the private ones, you may miss some.
Also if there's ever logic to be introduced in the setter method, you wont have to worry about changing more than 1 location for it.
If the value that you are assigning to the property is a known or verified value, you could safely use the private variable directly. (Except perhaps in some special situations, where it would be obvious why that would be bad.) Whether you do or not is more a matter of taste or style. It's not a performance issue either, as the getter or setter will be inlined by the compiler if it's simple enough.
If the value is unknown to the class, you should use the property to set it, so that you can protect the property from illegal values.
Here's an example (in C#):
public class Something {
private string _value;
public string Value {
get {
return _value;
}
set {
if (value == null) throw new ArgumentNullException();
_value = value;
}
}
public Something() {
// using a known value
_value = "undefined";
}
public Something(string initValue) {
// using an unknown value
Value = initValue;
}
}
If you use the getter you're ensuring you'll get the value after any logic/decisions have been applied to it. This probably isn't your typical situation but when it is, you'll thank yourself for this.
Unless I have a specific use case to use the internal field directly in the enclosing class, I've always felt that it's important to use access the field the same way it is accessed publicly. This ensures consistency in the return values across the board should there ever be any need to add some post-processing to the field via the getter method, or property. I feel like it's perfectly fine to access the raw field if you want its raw value for one reason or another.
More often than not, the getter encapsulation is plain and simple boilerplate code -- you're most likely not returning anything other than the field's value itself. However, in the case where you may want to change the way the data is presented at some point in the future, it's one less refactoring you have to make internally.