Has anyone used GraniteDS successfully with a plain Java client and lazy-loading (a real Java client or a Java server application calling another server)?
Is any special client-side initialization needed? (the docs say nothing about this so we assumed no need, simply took the example code)
Based on the docs (3.0.M2), we have created a Spring backend and a Java client which works for simple POJOs but fails when Hibernate-loaded POJOs would need to be returned (both the RemoteService and Tide versions fail with the same deserialization exceptions).
Currently, we don't have a client-side GraniteDS configuration file, only this code:
String baseURL = "http://localhost:8080/WebApp_Development_Client_Maven/";
URI uri = new URI(baseURL + "graniteamf/amf.txt");
Transport tr = new ApacheAsyncTransport();
tr.start();
AMFRemotingChannel ch = new AMFRemotingChannel(tr, "graniteamf", uri);
RemoteService srv = new RemoteService(ch, "userService");
List users = (List)srv.newInvocation("listUsers").invoke().get().getData();
The de-serialization exception:
Caused by: java.lang.RuntimeException: The ActionScript3 class bound to limes.core.model.security.User (ie: [RemoteClass(alias="limes.core.model.security.User")]) implements flash.utils.IExternalizable but this Java class neither implements java.io.Externalizable nor is in the scope of a configured externalizer (please fix your granite-config.xml)
at org.granite.messaging.amf.io.AMF3Deserializer.readAMF3Object(AMF3Deserializer.java:500)
at org.granite.messaging.amf.io.AMF3Deserializer.readObject(AMF3Deserializer.java:130)
at org.granite.messaging.amf.io.AMF3Deserializer.readObject(AMF3Deserializer.java:92)
... 36 more
Context:
We have a client-server Java/Swing application that was originally designed for intranet use (utilizes Hibernate 3 as the ORM). It also works through the internet but the PostgreSQL database connection very often breaks which makes the client unreliable (random freezes due to lost/broken db connection). This seems to be impossible to solve correctly (the easy measures like manual re-connection is already implemented)
We need to deploy the app over the internet and since the complex logic is already refactored into service classes we would like to leave the GUI mostly unchanged and remote the service classes. We are moving the persistence layer and the service classes into a Spring backend and would like to use GraniteDS because transparent lazy-loading is heavily utilized in the application so it would be very hard to replace it with DTO usage and/or Initializers.
I have not found plain-Java client examples, only a JavaFX example app which is so heavily tied to JavaFX that it seems very hard to transform into a plain-Java client (even trying it out is slightly problematic on Linux since it has no Webstart config included).
It seems that lazy-loading doesn't work in this version of GraniteDS (3.0.0.M2) with the plain-Java client.
https://groups.google.com/forum/#!topic/graniteds/KDWNY31lG0I
In theory, it works in the JavaFX environment but it was implemented in a way that plain-Java clients cannot use transparent lazy loading.
Also, GraniteDS doesn't support lazy-loading on single entities, only on collections which makes it unsuitable for projects using such relations. Personally, I think this is a glaring omission especially since they often refer to their lazy-loading support as "full".
Unfortunately, the documentation doesn't say anything about the lazy-loading limitations and also fails to make the distinction between the capabilities of GraniteDS with JavaFX and plain Java.
Related
I'm new to Camunda and still trying to figure out what things are possible.
Camunda BPM provides at least three ways to create custom forms:
Web-based form using AngularJS https://github.com/camunda/camunda-bpm-examples/tree/master/sdk-js/browser-forms-angular
Web-based form using JSF https://github.com/camunda/camunda-bpm-examples/tree/master/bpmn-model-api/generate-jsf-form
Embedded task form using several mechanisms https://github.com/camunda/camunda-bpm-examples/tree/master/usertask
I suppose I can customize a form any of those ways, but I wonder if I can create "on-the-fly" customization based on a pre-defined template stored in a database.
For example, I have a process of handling customer requests. They usually want something from three categories: A, B, and C.
FormA, FormB, and FormC are different but having typical fields for those kinds of requests.
Is there any way to add FormD in Camunda without re-deploy and changing source code of the task/process?
I mean just add a template of FormD in the database and see changes on the next process start.
Best regards, Ivan
You can bundle process models and custom html template in a deployment and hot deploy it together. No server restart required.
You can do this via Cockpit (if EE) or REST API:
https://docs.camunda.org/manual/develop/reference/rest/deployment/
One possible way to do that is through custom form builder using external service form.io - https://forum.camunda.org/t/form-builder-drag-and-drop-form-server-validations/1092/14
Based on the answer from Camunda BPM forum: https://forum.camunda.org/t/is-it-possible-to-create-on-the-fly-changing-form/20683
So, theoretically it's achievable I assume.
I have an application with Vaadin 8 and Spring Boot. Currently, I'm in progress of adding authentication to this app. So, I enabled Spring Security and started tinkering with it. Basically, I followed this tutorial: https://vaadin.com/tutorials/securing-your-app-with-spring-security/setting-up-spring-security
The approach, described there, works fine, however, I'm slightly disturbed by the fact that /VAADIN/** path needs to be publicly available (otherwise, Vaadin doesn't work). I mean, of course, I have protected particular pages by their paths (e.g. /admin) and unauthenticated users won't be able to open them, but isn't exposure of /VAADIN/** path dangerous? What if some hijacker tries to send some request to the Vaadin servlet outside of the UI (by simply curling it) with some specific headers/parameters? Is it possible that by formatting such request in some malicious way, the data will be actually returned to this hacker, bypassing Spring Security?
but isn't exposure of /VAADIN/** path dangerous
It is not dangerous per ce. The framework itself has just some generic parts there, like static resources for the client, like the widgetset and theme. Having said that, it is of course to be noted it application design. For example you should not put something that includes confidential info in your app as ThemeResource, but use ClassResource instead and things like that.
I'd like to design a portable application that is using Spring with JPA, but doesn't deal with Hibernate to make it possible to easily to port it to Google Apps Engine. In case of data persistence everything can be designed well, while I don't see any "spring data way" to instrument the classes for embedded internal Lucene usage (i.e without using of Solr as external webservice on the different URL). So, i'd like to have the local Lucene embedded into my Spring app (that will make possible to replace it with Luceneappsengune implementation), while having all boilerplate code to be handled on the way it is done with solr-spring-data. Hibernate Search annotations also doesn't work for me in this case. Any thoughts, how to do it?
So in examples I see that the almost the only bean configured is
#Bean
public SolrClient solrClient() {
return new HttpSolrClient("http://localhost:8983/solr");
}
Why don't we have the similar adapter for the internally used Lucene?
I am trying to implement row level security so our application can enforce more stringent access control.
One of the technologies we are looking into is Oracle's Virtual Private Database, which allows row level security by basically augmenting all queries against specific tables with a where clause predicate. Since we are in a web environment, we need to set up a special context within Oracle, inside a single request's thread. We use connection pooling with a service account.
I started to look into Eclipse Link and Hibernate. Eclipse Link seems to have events that fit perfectly into this model.
This would involve us migrating from hibernate, which is not a problem, but we would then be bound to EL for these events.
Oracle seems to imply that they implement at the data source level in Web Logic product.
The context is set and cleared by the WebLogic data source code.
Question: Is it more appropriate to do this at the DataSource level with some series of events. What are the events or methods that I should pay the most attention too?
Added Question: How would I extend a connection pool to safely initialize an oracle context with some custom data? I am digging around in Apache, and it seems like extending BasicDataSource doesn't give me access to anything that would allow me to clean up the connection when Spring is done with it.
I need to set up a connection, and clean up a connection as the exit / enter the connection pool. I am hoping for an implementation that is so simple, no one can mess it up by breaking some delicate balance of products.
- Specifically we are currently using Apache Commons DBCP Basic Data Source
This would allow us to use various ways to connect to the database and still have our security enforced. But I don't see a great example or set of events to work with, and rolling my own security life cycle is never a good idea.
I eventually solved my problem by extending some of the Apache components.
First I extended org.apache.commons.pool.impl.GenericObjectPool and overrode both borrowObject() and returnObject(). I knew the type of the objects in the pool (java.sql.Connection) so I could safely cast and work with them.
Since for my case I was using Oracle VPD, I was able to set information in the Application context. I recommend you read about that in more depth. It is a little complicated and there are a lot of different options to hide or share data at various contexts level, and across RAC nodes. Start
In essence what I did was generate a nonce and use it to instantiate a session within oracle, and then set the access level of the user to a variable in that session, that the Oracle VPD policy would then read and use to do the row level filtering.
I instantiated and destroyed that information in my overridden borrowObject() and returnObject() The SQL I ran was something like this:
CallableStatement callStat =
conn.prepareCall("{call namespace.cust_ctx_pkg.set_session_id(" + Math.random() + ")}");
callStat.execute();
Note math.random() isn't a good nonce.
Next was to simply extend org.apache.commons.dbcp.BasicDataSource and set my object pool by overriding createConnectionPool(). Note that the way I did this disabled some functionality I did not need, so you may need to rewrite more or less than I did.
You can try any object level security mechanism for simplicity, like Spring Security ACL.
You will want to do this at the application layer. You will want a pre-commit hook and a post read hook.
The pre-commit hook is used to ensure that data from the client is being presented by a user authorized to modify that data. This prevents an unauthorized user from overwriting data that they shouldn't be able to access.
It's not intuitive, but the post read hook is used to keep the client from accessing data the user shouldn't be allowed to view. This happens post-view because this is being enforced at the application layer, not at the data layer. The application has no way to know if the caller is allowed to access the data until it's been retrieved from the data layer. In the post read hook you evaluate the credential on each row returned against the credential of the logged in user in order to determine whether or not access is allowed. If access is denied on any row then an exception would be raised and the data would not be returned to the client.
Application level security done in this way requires that you have a way to connect each row in a table to a permission/role required to access it and a way to evaluate a user's permissions on the server at runtime.
Hope that helps.
You will get better control by using one of the other Commons DBCP Datasources.
The Basic one is just that: basic :)
The ones in org.apache.commons.dbcp.datasources package gives you more fine-grained control.
Assume the follwing method:
Test getTest()
{
Properties props = new Properties();
props.put(javax.naming.Context.SECURITY_PRINCIPAL, "OtherUser");
props.put(javax.naming.Context.SECURITY_CREDENTIALS, "OtherPassword");
InitialContext ic = new InitialContext(props);
return (TestHome)PortableRemoteObject.narrow(ic.lookup("ejb/Test"),
TestHome.class).create();
}
If this method (in an EJB) is called from a client using user "MyUser" I'd like it to return an EJB with a different caller principal. Calls to Test made by the client would then be noted as being from "OtherUser". i.e. I have programmactially changed a client's caller principal for a given EJB.
However, I find no text on this in the Java EE specs and although it works on our current Java EE app-server (Sybase EAS 4.1), I'd like to ask you if this is a Java EE standard approach or not.
A standard way of handling login/logoff is JAAS. I don't know if it's fair to say that it is the standard, but it's supported by the Java EE servers I've worked with so far (JBoss, Websphere), and apparently also by Sybase EAS.
JBoss, for instance, comes with several predefined login modules for Database and LDAP and whatnot, that you just have to declaratively configure for your application. However, you are also completely free to write your own login module by implementing the respective interface (javax.security.auth.spi.LoginModule).
Take a look at the JAAS Reference Guide.
About your code snippet: I don't know if that'll work on other app servers. This is EJB 1.1, and thus really, really old stuff. You should definitely look at EJB 3.1 and consider modernizing your application anyway.
If I get this right this should link a username to an EJB across more than one methodcall, which in my opinion is a state. I guess the standard for this would be to create a Stateful SessionBean with a setUser(String name) method. In a stateless bean you would have to pass the userName (or properties object) on each methodcall.