extdirectspring methods not working - java

I set up ext direct for my Spring MVC app using extdirectspring. I am able to retrieve primitives and Strings and use them in ext.js. When I try to retrieve a list of objects, I am getting "undefined" on the javascript side. Is there anything special that I need to do to the Person class to get it to work?
I annotated the following code:
#ExtDirectMethod(ExtDirectMethodType.STORE_READ)
#Override
public Collection<Person> getPeople(String groupId) {
Group group = GroupManager.getGroup(groupId);
return group.getPeopleList();
}
This is what I am using on the client side:
directory.getPeople(id, function(result) {
console.log(result);
});
Here is what app.js looks like:
Ext.ns('Ext.app');
Ext.app.REMOTING_API = {
"actions":{
"directory":[{
"name":"getID","len":0
},{
"name":"getPeople","len":1
}
]}‌​,
"type":"remoting",
"url":"/test/action/router"
};

Have you tried using the ExtDirectStoreResponse class? It does use a collection but also manages some useful values for use in the store.
#ExtDirectMethod(ExtDirectMethodType.STORE_READ)
public ExtDirectStoreResponse<Person> load()
{
Group group = GroupManager.getGroup(groupId);
Collection<Person> people = group.getPeopleList();
return new ExtDirectStoreResponse<Person>(people.size(), people);
}
This is the approach to use when using the STORE_READ. That method annotation is expecting the request to come in matching values in the ExtDirectStoreReadRequest class. This is the reference to use when doing a store read. https://github.com/ralscha/extdirectspring/wiki/Store-Read-Method
Also, instead of calling the method directly, you would set up an ExtJs store and call
store.load();

Related

How to map from Page<ObjectOne> to Page<ObjectTwo> in Spring Data 2?

I'm looking at some old code and I'm trying to re-write it however I encountered a problem.
This is the old code that works perfectly fine:
public Page<SearchResult> search(String text, int pageNumber) {
PageRequest request = PageRequest.of(pageNumber-1, itemsPerPage);
Page<Profile> results = profileDao.findByInterestsNameContainingIgnoreCase(text, request);
Converter<Profile, SearchResult> converter = new Converter<Profile, SearchResult>() {
#Override
public SearchResult convert(Profile profile) {
return new SearchResult(profile);
}
};
return results.map(converter);
}
But I'm using Spring Data 2, where the Page map method takes a Function instead of a Converter so I don't know how to re-write this.
I read this topic: How to map Page<ObjectEntity> to Page<ObjectDTO> in spring-data-rest but I failed to convert Page<Profile> into Page<SearchResult> because I still don't fully understand this Function concept.
Could someone translate code snippet from above using Spring Data 2 method (Function instead of a Converter)?
Based on your example I would implement the map function as follows:
Page<SearchResult> searchResultPage = results.map(profile -> new SearchResult(profile));
If you are interested in a short introduction to lambda expressions and functional interfaces I recommend checking out the following summary: https://www.baeldung.com/java-8-lambda-expressions-tips

I want to filter a list of object in groovy

This is my groovy class
Asset {
ObjectState objectState = ObjectState.CURRENT
String description
#NotEmpty(message = "*Please provide a asset name")
#Length(min = 2, max = 50, message = "*Asset name must have characters between 2 and 50")
String assetName
#DBRef
Company company
}
I want to find those assets of a particular company which contains "test" in assetName and description
Now i implemented the business logic like this
#Override
Page<Asset> fetchAssetsBySearchStringAndObjectStateAndCompany(Company company, Pageable pageable, String searchQuery) {
ObjectState objectState = ObjectState.CURRENT
if (!pageable) {
pageable = PageRequest.of(0, 10, Sort.Direction.DESC, "lastUpdated")
}
if (searchQuery) {
Page<Asset> assets = assetRepository.findAllByCompanyAndObjectState(company, pageable, objectState)
List<Asset> filteredAssets = []
assets.each {
if (it.assetName.contains(searchQuery) || it.description.contains(searchQuery)) {
filteredAssets.add(it)
}
}
return filteredAssets // i want this list in pagination object
} else {
return assetRepository.findAllByCompanyAndObjectState(company, pageable, objectState)
}
}
I find all the assets of a company -
Filter out the "test" string using groovy closure - assets.each { }
Now my filteredAssets contains required result but i want this in pagination object
Now my question is
1- Is this approach is efficient
2- How to convert filteredAssets in Page
I also tried to use mongo native query but i am unable to convert it to spring boot
#Query('''{
'company': ?0,
$or :
[
{'assetName' : { $regex: ?1, $options:'i' }},
{'description' : { $regex: ?1, $options:'i' }},
]
}
''')
Page<Asset> findAllByCompanyAndAssetNameOrDescription(Company company, String assetName, Pageable pageable)
I don't have a specific answer but my suggestion is that your first approach is not going to work at a higher level because you are filtering the results after the pagination has been performed by the initial query. So you will potentially end up with less than the desired page size (or even an empty result) even though there are valid results that could have been returned by the query.
In other words, to achieve this you really do need to use the second approach of constructing a native query that incorporates the filtering. To resolve why that is not working, you would need to post more information about the kind of errors you are seeing (or possibly put it as a separate question and close this one out).
EDIT: to answer the question more specifically - if you choose to persist with the approach, it looks to me like you can construct your own Page object by harnessing the Spring data PageImpl object which has a usable constructor from a list of elements. You can simply construct this object from your filtered list of elements - ie: instead of this:
...
return filteredAssets
Do this:
return new PageImpl(filteredAssets)
If you want to be more idiomatic with your groovy code I would also suggest to change the filtering operation to use findAll. In that case the code gets more compact:
return new PageImpl(assets.findAll { it.assetName.contains(searchQuery) })
Once again though I would caution that from looking at your problem I don't think it's going to have the result you actually want.

Wiremock verify headers contains many values via custom ValueMatcherStrategy

I'm using wiremock to test a client. One particular test is to verify that the client send one header with a comma separated list of values.
However those values are from an unordered collection. So it can be first,second or second,first and both are valids.
Sadly, I cannot find any ValueMatchingStrategy that can be used for that. containing expect only one value.
I tried to build a custom ValueMatcherStratgey but the isMatchFor method is never called.
new ValueMatchingStrategy(){
#Override
public ValuePattern asValuePattern() {
return new ValuePattern(){
#Override
public boolean isMatchFor(String value) {
return value.contains("first") &&
value.contains("second") &&
value.contains(",");
}
};
}
}
Is there an easier way to verify that a header contains more than one value ? Or how can I create a custom matcher ?
Have you looked at the doc for creating custom matchers?
http://wiremock.org/docs/extending-wiremock/#custom-request-matchers

How to pass non-primitive Object from Java to JS by Android addJavascriptInterface?

I've had a trouble on this topic (for days).
For instance, basically, I want to pass a Java WebSocketClient object to Android Webview JS on demand, so wrote a code referring to:
http://foretribe.blogspot.com.au/2013/08/how-to-make-android-webview-support.html
https://github.com/thinksource/vw_websocket/blob/master/src/com/strumsoft/websocket/phonegap/WebSocketFactory.java
JAVA
wv.addJavascriptInterface(new WebSocketFactory(), "factoryJ");
public class WebSocketFactory {
//.............
public WebSocket getInstance(String url) {
socket = new WebSocket(new URI(url));
return socket;
}
}
JS
var url = "ws:someaddress";
var ws = factoryJ.getInstance(url);
console.log(ws.toString()) // object pointer displayed
console.log(ws.getReadyState()); //Uncaught Error: Error calling method on NPObject!
Uncaught Error: Error calling method on NPObject!
This concept does not work at least for me avove Android4.2+.,
because addJavascriptInterface() only works with Java primitive types and Strings.
cf)
Passing a JavaScript object using addJavascriptInterface() on Android
Error calling method on NPObject! in Android 2.2
As far as I know, the only way to pass JAVA object to JS is :
wv.addJavascriptInterface(JavaObject, "JsObject");
Sure, this should work fine as long as a passing JavaObject is pre-determined, but since WebSocket Object(s) is on-demand, I need to hack somehow for this.
So, I prepare JavaObject as some Array of WebSocket .
WebSocketNew[] ws = new WebSocketNew[99999];
wv.addJavascriptInterface(ws, "wsJ");
Unfortunately, the JS treats wsJ[n] as undefined ; appears it's also not allowed to pass ArrayObject.
I've read JSON or JSON array of Java can be passed, but it's string after all and cannot be this solution, am I correct?
Probably, back in old days, Android Java-JS interaction is implemented more freely, but under security issues, they restrict more (the annotation #JavascriptInterface is the one, and not only this but also other factors ) Android 4.2.1, WebView and javascript interface breaks
How to pass non-primitive Object from Java to JS by Android addJavascriptInterface?
Any thought?
Thanks.
You are correct that Javascript Interface methods can only return strings and primitive types. If you need to return a more complex object, you can try serializing the object to JSON. But, that only works for model-level objects. If you need to return a class which contains functionality, the only way I know of to do this is to wrap the class, and expose each of its methods as a #JavascriptInterface. For instance:
class Foo {
private WrappedClass myWrappedClass;
public Foo(WrappedClass classToWrap) {
myWrappedClass = classToWrap;
}
#JavascriptInterface
public String doSomething1() {
return myWrappedClass.doSomething1();
}
#JavascriptInterface
public int doSomething2() {
return myWrappedClass.doSomething2();
}
// Etc.
}
This is pretty tedious.
But, it looks like you're trying to use websockets. Have you considered Socket.io? It would allow you to use web sockets in Javascript, rather than relying on a JavascriptInterface.
http://socket.io
This has been one of the most hectic hack for me.
The major problem occurs from Android UI-thread and non-UI-thread bind with addJavascriptInterface
Firstly, my mention:
As far as I know, the only way to pass JAVA object to JS is :
wv.addJavascriptInterface(JavaObject, "JsObject");
is wrong.
In fact, I could pass WebSocketNew= my custom Java object properly to JS as return value of getInstance.
However, the object intended to pass/return to JS must be in scope of Android UI-thread.
If we just do return new WebSocketNew(new URI(url))), it's not found by JS, probably because JS runs in UI-thread, and the origin runs on non-UI-thread of addJavascriptInterface.
As I mentioned earlier, since WebScoket instance is on-demand, so I decided to create Object pool in UI-thread first.
This can be done with HashMap with the requested url String.
Java
final HashMap<String, WebSocketNew> ws = new HashMap<>();
//runs on non-UI-thread
class WebSocketFactory
{
public WebSocketFactory()
{
}
#JavascriptInterface
public WebSocketNew getInstance(String url)
{
System.out.println("============WebSocketFactory============getInstance " + url);
try
{
ws.put(url, new WebSocketNew(new URI(url)));
ws.get(url).connect();
System.out.println("=====WebSocketNew=====" + url + " " + ws.get(url).getReadyState());
return ws.get(url);
}
catch (Exception e)
{
System.out.println("==========ERROR");
return null;
}
}
}
wv.addJavascriptInterface(new WebSocketFactory(), "factoryJ");
wv.loadUrl("file:///android_asset/Content/app.html");
JS
window.WebSocket = function(url)
{
console.log('####################creating new WebScoketInstance JS ' + url);
var p = {
url: null
};
p.url = url;
var ws = factoryJ.getInstance(p.url);
var obj = {
send: function(data)
{
console.log('--- send: function(data)----- ws.send1(data);------');
ws.send1(data);
},
//.......
//.......
}
return obj;
};
The JS code is related to topic : JavaScript Event implementation to Closure based Object

Play 2 - How to set default value of template's parameter from Java controller?

Is it possible to define optional parameter when rendering an scala template in Play Framework 2?
My controller looks like this:
public static Result recoverPassword() {
Form<RecoveryForm> resetForm = form(RecoveryForm.class);
return ok(recover.render(resetForm));
// On success I'd like to pass an optional parameter:
// return ok(recover.render(resetForm, true));
}
My Scala template looks like this:
#(resetForm: Form[controllers.Account.RecoveryForm], success:Boolean = false)
Also tried:
#(resetForm: Form[controllers.Account.RecoveryForm]) (success:Boolean = false)
In both cases i got "error: method render in class recover cannot be applied to given types;"
From Java controller you can't omit assignation of the value (in Scala controller or other template it will work), the fastest and cleanest solution in this situation is assignation every time with default value, ie:
public static Result recoverPassword() {
Form<RecoveryForm> resetForm = form(RecoveryForm.class);
if (!successfullPaswordChange){
return badRequest(recover.render(resetForm, false));
}
return ok(recover.render(resetForm, true));
}
Scala template can stay unchanged, as Scala controllers and other templates which can call the template will respect the default value if not given there.
BTW: as you can see, you should use proper methods for returning results from Play's actions, see ok() vs badRequest() also: forrbiden(), notFound(), etc, etc
You can also use flash scope for populating messages and use redirect() to main page after successful password change, then you can just check if flash message exists and display it:
public static Result recoverPassword() {
...
if (!successfullPaswordChange){
return badRequest(recover.render(resetForm, false));
}
flash("passchange.succces", "Your password was reseted, check your mail");
return redirect(routes.Application.index());
}
in ANY template:
#if(flash.containsKey("passchange.succces")) {
<div class="alert-message warning">
<strong>Done!</strong> #flash.get("passchange.succces")
</div>
}
(this snippet is copied from Computer Database sample for Java, so you can check it on your own disk)

Categories

Resources