Daily development Miscellany --2020 / 02/25, 26, --- not finishing system

How to specify the Java compiler options with gradle of GroovyCompiler?

So designated:

	compileGroovy {
	    options.compilerArgs << "-Xlint:unchecked"
	}

Groovy and Java mixed-use project, how to make Java class can have access to the Groovy class?

Configure the following content gradle in:

// 下面的配置会让gradle先编译groovy,后编译java,以便在 java 中使用 groovy 类
// ref: https://coderwall.com/p/wuqopq/compile-groovy-before-java-in-gradle-build
// 因为 groovy 插件默认会先编译 java 后编译 groovy,导致 java 找不到 groovy 的类。
sourceSets {
    main {
        groovy {
            // this makes the groovy-compiler compile groovy- as well
            // as java-files.
            // Needed, because java is normally compiled before groovy.
            // Since we are using groovy objects from java, we need it
            // the other way round.
            srcDirs = ['src/main/groovy', 'src/main/java']
        }
        java {
            srcDirs = [] // don't compile Java code twice
        }
    }
}

How to solve the "unchecked cast" compilation warnings?

Warning follows:

public Token deserialze(DefaultJSONParser parser, Type type, Object fieldName) {
                 ^
  返回类型需要从Token到T的未经检查的转换
  其中, T是类型变量:
    T扩展已在方法 <T>deserialze(DefaultJSONParser,Type,Object)中声明的Object

We did not find a solution to solve , but you can use annotation tells the compiler javac do not show unchecked warning.

@SuppressWarnings("unchecked")

In fact, the definition of the need to define a generic interface T Bar (fastjson project)? The following code

public interface ObjectDeserializer {
    /**
     * fastjson invokes this call-back method during deserialization when it encounters a field of the
     * specified type.
     * <p>In the implementation of this call-back method, you should consider invoking
     * {@link JSON#parseObject(String, Type, Feature[])} method to create objects
     * for any non-trivial field of the returned object. 
     *
     * @param parser context DefaultJSONParser being deserialized
     * @param type The type of the Object to deserialize to
     * @param fieldName parent object field name
     * @return a deserialized object of the specified type which is a subclass of {@code T}
     */
    <T> T deserialze(DefaultJSONParser parser, Type type, Object fieldName);
    
    int getFastMatchToken();
}

T defined above is not clear what effect this.

Groovy classes of property (property) default is private level, how to set the property is protected, and get / set methods are public?

Groovy look at the traits (characteristics) related documents , will be able to know.
First, to be able to distinguish between the two concepts confusing "fields" and "property".

  • field fields: fields field is known as java class, you must bring the definition of the groovy private, protected or public access modifier, groovy rely on whether there is this qualifier to determine your code is in the definition of a field or property.
  • property attribute: it is the property Java Bean defined in the specification, together with the corresponding fields that get / set methods. Must get, set methods to access the property.

Therefore, we should avoid from the rules so used, it needs to be designed such that the corresponding property field is certainly not a change protected, and used directly get, set method just fine. If groovy code, then use the properties and use the field is no different, with obj.name all the way on it.

If the property is used in the more traits should be noted, because the implementation class property defined traits can not override, the setting value does fit, as in the following sample code:

trait IntCouple {
    int x = 1
    int y = 2
    int sum() { x+y }
}
class Elem implements IntCouple {
    int x = 3                                       
    int y = 4                                       
    int f() { sum() }                               
}
def elem = new Elem()
assert elem.f() == 3

The result is a failure! Because elem.f () equal to 7! Rather than 3, because there is a separate object traits, Field of the object classes will not be implemented (Elem) changed.
To support the changing traits in the implementation class property, use only get, set method of defining traits, but do not directly use the field, like this:

trait IntCouple {
    int x = 1
    int y = 2
    int sum() { getX()+getY() }
}

On it, the value of elem.f () is now 7 a. The settings of the manner or also, as follows:

class Elem implements IntCouple {
    int f() { 
	      x = 3
	      y = 4
	      sum()
      }                               
}

Groovy's traits is very powerful, it is worth writing a separate article.

IDEA how to get rid of "unused" warning?

Add @SuppressWarnings ( "unused") on the method or class notes can be.

How to make Groovy Do not call DefaultGroovyMethods.addAll () method, but JavaFX ObservableListWrapper of addAll () method?

EVERYTHING

Groovy spread the operator '*' does not support multi-stage deployment

The following code does not set up

list*.staff*.status = newStatus

It can only be launched once, and only the right side of the equal sign, as follows

def staffList = list*.staff

GString property can not be resolved correctly

If the class defines the field, the get function is defined, then the GString in this.name resolves to the field rather than as a property access, to call the get function. E.g:

class TenantUser {
	private ObjectProperty<TenantUserStatus> status = new SimpleObjectProperty<>()
    TenantUserStatus getStatus() {
        return status.value
    }
    def test() {
    	"${this.status.name}"
    }
}
def user = new TenantUser()
// 编译会报错:找不到 类型 ObjectProperty<TenantUserStatus> 的 name 方法

Description, GString in $ {this.status.name} this.status to resolve the property field instead.
The solution is to use a function in GString get in.

How Slurper Groovy word that often appear understanding and translation?

For example JsonSlurper, XMLSlurper and so on.
Slurper Silent Hill 3 game monsters, on the head of a mouth, slurp prey jumped from his head. Therefore, we can Slurper translated as "eat goods" Yes, that eat goods, if translated as "slurp beast", it makes going to guess what is "slurp", rather than "eat goods" is more image.
Therefore, JsonSlurper is Json food goods, XMLSlurper is XML food goods.

How will a Groovy map of key / value pairs one-time copy to the property of another object?

The key is to map the corresponding object attribute name, value assigned to the property. The goal is to generate the Groovy Object json slurper into an object class is specified.
Target logical following sample code:

def jsonObject = jsonSlurper.parseText "{name:'abc'}"
User user = jsonObjectToUser(jsonObject)
assert user instanceof User

Ideas:
there is a way to help is InvokeHelper.setProperties (target, properties)

User user = User.findById('1')
User copyUser = new User()
InvokerHelper.setProperties(copyUser, user.properties)
copyUser.language = 'French'
copyUser.save(flush:true)

Another idea is to use the cast operator "as", refer to as a document .
The following is a method of use as

class Identifiable {
    String name
}
class User {
    Long id
    String name
    def asType(Class target) {                                              
        if (target == Identifiable) {
            return new Identifiable(name: name)
        }
        throw new ClassCastException("User cannot be coerced into $target")
    }
}
def u = new User(name: 'Xavier')                                            
def p = u as Identifiable                                                   
assert p instanceof Identifiable                                            
assert !(p instanceof User)       

Because JsonSlurper parsing json object to the Map, so we need to dynamically add a Map function asType ().
How to achieve it? With traits of it. traits can dynamically add a class interface. Use up more trouble with traits, should be used to achieve Category.

The following traits code does not work, it will throw an exception .

trait MapToClass {
    /**
     * 支持将 Map 转换为 TenantStaff 类
     * @param target 要转换的目标类
     */
    def asType(Class target){
        switch (target) {
            case TenantStaff:
                TenantStaff targetObject = new TenantStaff()
                // 复制key/value到 targetObject 的属性上
                this.entrySet().collect {
                    targetObject.setProperty(it.key as String, it.value)   //  <1>
                }
                return targetObject
            case StringProperty:
                // 取 StringProperty 变成 json串的object后的 value 属性,因为这个对象的格式类似下面这样:
                // {value=老杨 (在线), bean=null, bound=true, name=, valueSafe=老杨 (在线)}
                return new SimpleStringProperty(this.value)
        }
        throw new ClassCastException("Unsupport coercion from Map to class $target")
    }
}

<1> Here you will throw an exception that can not be Map cast into StringProperty. The reason is groovy before setting the property value, do the cast action parameters, and our argument is a complex object that is StringProperty, it is serialized into the json object, when deserialization time, will be read as JsonSlurper Map objects, giving rise to the above cast exception. Here we use is the same category to achieve will throw an exception, as will call setProperty () method.

Category switching to be implemented or not, throw an exception.

It seems to use ExpandoMetaClass achieved.

Throws place:

//----------------------------------------------------------------------
// executing the getter method
//----------------------------------------------------------------------
if (method != null) {
    if (arguments.length == 1) {
        newValue = DefaultTypeTransformation.castToType(
                newValue,
                method.getParameterTypes()[0].getTheClass());       <1>
        arguments[0] = newValue;
    } else {
        newValue = DefaultTypeTransformation.castToType(
                newValue,
                method.getParameterTypes()[1].getTheClass());
        arguments[1] = newValue;
    }
    method.doMethodInvoke(object, arguments);
    return;
}
        
private static Object continueCastOnSAM(Object object, Class type) {
...
    return InvokerHelper.invokeConstructorOf(type, args);       <2> 
...
}

<1> this place due to the anomaly.
<2> The place eventually thrown.

So we should also study how to dynamically add a constructor for a Class job.

Mainly because the attribute type is javafx of StringProperty class class, which has already default constructor.

If you put it into a specific category, such as SimpleStringProperty another exception occurs, it can not cast abnormal parameter values.

Finally, a solution is to write a special conversion logic for each property:

    /**
     * 支持将 Map 转换为 TenantStaff 类
     * @param target 要转换的目标类
     */
    static def asType(Map self, Class target) {
        switch (target) {
            case TenantStaff:
                TenantStaff targetObject = new TenantStaff()
                // 复制key/value到 targetObject 的属性上
                self.entrySet().forEach {
                    switch (it.key) {
                        case "elementNameProperty":
                            targetObject.elementNameProperty.value = it.value.value
                            break
                        case "statusProperty":
                            targetObject.statusProperty.value = it.value.value as TenantUserStatus
                            break
                        case "children":
                            targetObject.children.addAll(it.value as List)
                            break
                        default:
                            targetObject.setProperty(it.key as String, it.value)
                    }
                }
                return targetObject
        }
        throw new ClassCastException("Unsupport coercion from Map to class $target")
    }

Summary: Groovy setProperty method requires a dynamic attribute type can be instantiated normal, and the value of the object to be set must be converted directly to the property type, but not by other additional cast manner. This is also the Groovy capacity limitations of it.

Why Groovy extension of the Date function no?

Today in the development, need Date.parse ( "yyyy-MM-dd HH: mm: ss", "2020-02-28 12:30:00") This method, but found not find the compiler reports parse () function is obsolete.

The original is the lack of dependency groovy-dateutil JAR added to rely, as follows

implementation 'org.codehaus.groovy:groovy-all:2.5.9'
implementation 'org.codehaus.groovy:groovy-dateutil:2.5.9'

Further LocalDate extension may also be used, as follows:

org.apache.groovy.datetime.extensions.DateTimeStaticExtensions#parse(java.time.LocalDate, java.lang.CharSequence, java.lang.String)

So we have to write, pay attention to the pattern parameters into the final surface:

LocalDate.parse("2020-02-28 12:30:00", "yyyy-MM-dd HH:mm:ss")

Groovy some useful links to related resources

About WebSocket

  • Introduction websock the basic concepts and development of technology; This blog describes the more technical details, such as data frames, API.
  • grails 有 websocket plugin
  • WebSocket protocol
    • Which is described on the "reconnect" to resolve my doubts. See 7.2.3. Recovering from Abnormal Closure
  • spring websocket regarding the usage
  • websocket 的 java client libarary

About Vert.x framework

Currently my understanding, Vert.x is Java, Node.js, all calls are asynchronous.
And node.js, as are the use of Reactor Pattern programming. And the difference is node.js, vert.x using a plurality of event-loop thread, which can run on a CPU core with a plurality of vert.x example, this mode is called Multi-Reactor Pattern.

This programming mode, the programmer of the most important requirement is "not blocking Event Loop Thread"! For example, can not wait in your Handler in, sleep and so on.

For clog a little while (not more than a few seconds) tasks can be performed with executeBlocking () method. But the longer task, it must provide a dedicated thread by the application itself to perform, and then use the event-bus or runOnContext to and interact with the vert.x.

This looks and how JavaFX UI thread so similar pattern

vertx.executeBlocking({ promise ->
  // Call some blocking API that takes a significant amount of time to return
  def result = someAPI.blockingMethod("hello")
  promise.complete(result)
}, { res ->
  println("The result is: ${res.result()}")
})

Here, did not feel the advantages Vert.x, is not using the thread pool is the same to develop it. But it is still a little subtle differences, this nuance is Vert.x use of Reactor-Pattern, like Node.js as use everywhere, even forcing programmers to use Reactor-Pattern, because you can wait for CPU and IO wasted time is greatly reduced, so it did improve server efficiency, that is, a single server can handle more concurrent requests.

Another advantage is that following various "asynchronous coordination", this model can be easily combined with the results of asynchronous tasks.

Async coordination asynchronous coordination

That is, multiple asynchronous execution of the "future" objects in various combinations, to get a new "future" objects.

  • CompositeFuture.all all the success to be successful, there is a failure is considered a failure, and ranging from the end of all future
  • CompositeFuture.join and all the same, but will wait for the end of all future
  • compose the order of execution

Vert.x Forecast

Because Node.js is already the world's major electricity providers, large flow rate widely used, one of which is due to asynchronous server development model brings efficiency, because a javascript completed the development of the whole stack, high development efficiency.
So think of Java programmers, Groovy is Java, Javascript, then Vert.x is in Java Node.js, and if the Groovy language can be popular in the Java world, pop, then Vert.x is also expected in the Java world popular. But because Vert.x like Javascript Node.js so important for the world, because Node.js directly open up the front and back office development, Vert.x and can not penetrate into the front-end development, coupled with the Vert.x Node.js is a latecomer , vert.x up to the server, the server brought asynchronous programming to maximize the performance.

The conclusion is Vert.x prevalence and popularity will be proportional to the Groovy language, better able to complete the "high concurrency, high flow" of computing tasks on the server side, a short time success depends on world-class large electricity providers plant and medium-sized Internet companies to adopt and embrace, but in the long run, Java world to embrace the "asynchronous programming model" (so-called Reactive programming) will have to rely on vert.x, Spring5 +, or the Akka.

Reference material

Published 46 original articles · won praise 7 · views 80000 +

Guess you like

Origin blog.csdn.net/yangbo_hr/article/details/104500163