Skip to content
Snippets Groups Projects
Commit 99f2cafa authored by Xin.Zh's avatar Xin.Zh Committed by GitHub
Browse files

Merge pull request #122 from pantianying/master

generic#invoke (go to java)
parents 58a6aa06 a74d13d5
No related branches found
No related tags found
No related merge requests found
......@@ -38,6 +38,8 @@ const (
PREFIX_DEFAULT_KEY = "default."
DEFAULT_SERVICE_FILTERS = "echo"
DEFAULT_REFERENCE_FILTERS = ""
GENERIC_REFERENCE_FILTERS = "generic"
GENERIC = "$invoke"
ECHO = "$echo"
)
......
......@@ -30,6 +30,7 @@ const (
METHODS_KEY = "methods"
TIMEOUT_KEY = "timeout"
BEAN_NAME_KEY = "bean.name"
GENERIC_KEY = "generic"
)
const (
......
......@@ -66,6 +66,10 @@ func Load() {
logger.Errorf("[consumer config center refresh] %#v", err)
}
for key, ref := range consumerConfig.References {
if ref.Generic {
genericService := NewGenericService(key)
SetConsumerService(genericService)
}
rpcService := GetConsumerService(key)
if rpcService == nil {
......
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package config
type GenericService struct {
Invoke func(req []interface{}) (interface{}, error) `dubbo:"$invoke"`
referenceStr string
}
func NewGenericService(referenceStr string) *GenericService {
return &GenericService{referenceStr: referenceStr}
}
func (u *GenericService) Reference() string {
return u.referenceStr
}
......@@ -55,6 +55,7 @@ type ReferenceConfig struct {
Params map[string]string `yaml:"params" json:"params,omitempty" property:"params"`
invoker protocol.Invoker
urls []*common.URL
Generic bool `yaml:"generic" json:"generic,omitempty" property:"generic"`
}
func (c *ReferenceConfig) Prefix() string {
......@@ -110,7 +111,6 @@ func (refconfig *ReferenceConfig) Refer() {
regUrl.SubURL = url
}
}
if len(refconfig.urls) == 1 {
refconfig.invoker = extension.GetProtocol(refconfig.urls[0].Protocol).Refer(*refconfig.urls[0])
} else {
......@@ -157,6 +157,7 @@ func (refconfig *ReferenceConfig) getUrlMap() url.Values {
urlMap.Set(constant.RETRIES_KEY, strconv.FormatInt(refconfig.Retries, 10))
urlMap.Set(constant.GROUP_KEY, refconfig.Group)
urlMap.Set(constant.VERSION_KEY, refconfig.Version)
urlMap.Set(constant.GENERIC_KEY, strconv.FormatBool(refconfig.Generic))
//getty invoke async or sync
urlMap.Set(constant.ASYNC_KEY, strconv.FormatBool(refconfig.async))
......@@ -170,7 +171,11 @@ func (refconfig *ReferenceConfig) getUrlMap() url.Values {
urlMap.Set(constant.ENVIRONMENT_KEY, consumerConfig.ApplicationConfig.Environment)
//filter
urlMap.Set(constant.REFERENCE_FILTER_KEY, mergeValue(consumerConfig.Filter, refconfig.Filter, constant.DEFAULT_REFERENCE_FILTERS))
var defaultReferenceFilter = constant.DEFAULT_REFERENCE_FILTERS
if refconfig.Generic {
defaultReferenceFilter = constant.GENERIC_REFERENCE_FILTERS + defaultReferenceFilter
}
urlMap.Set(constant.REFERENCE_FILTER_KEY, mergeValue(consumerConfig.Filter, refconfig.Filter, defaultReferenceFilter))
for _, v := range refconfig.Methods {
urlMap.Set("methods."+v.Name+"."+constant.LOADBALANCE_KEY, v.Loadbalance)
......@@ -180,3 +185,11 @@ func (refconfig *ReferenceConfig) getUrlMap() url.Values {
return urlMap
}
func (refconfig *ReferenceConfig) GenericLoad(id string) {
genericService := NewGenericService(refconfig.id)
SetConsumerService(genericService)
refconfig.id = id
refconfig.Refer()
refconfig.Implement(genericService)
return
}
......@@ -25,16 +25,15 @@ import (
"syscall"
"time"
)
import (
"github.com/apache/dubbo-go-hessian2"
hessian "github.com/apache/dubbo-go-hessian2"
)
import (
"github.com/apache/dubbo-go/common/logger"
_ "github.com/apache/dubbo-go/common/proxy/proxy_factory"
"github.com/apache/dubbo-go/config"
_ "github.com/apache/dubbo-go/protocol/dubbo"
"github.com/apache/dubbo-go/protocol/dubbo"
_ "github.com/apache/dubbo-go/registry/protocol"
_ "github.com/apache/dubbo-go/filter/impl"
......@@ -65,7 +64,8 @@ func main() {
test1()
println("\n\ntest2")
test2()
println("\n\ntest3")
test3()
initSignal()
}
......@@ -288,3 +288,24 @@ func test2() {
}
println("error: %v", err)
}
func test3() {
var appName = "UserProviderGer"
var referenceConfig = config.ReferenceConfig{
InterfaceName: "com.ikurento.user.UserProvider",
Cluster: "failover",
Registry: "hangzhouzk",
Protocol: dubbo.DUBBO,
Generic: true,
}
referenceConfig.GenericLoad(appName) //appName is the unique identification of RPCService
time.Sleep(3 * time.Second)
println("\n\n\nstart to generic invoke")
resp, err := referenceConfig.GetRPCService().(*config.GenericService).Invoke([]interface{}{"GetUser", []string{"java.lang.String"}, []interface{}{"A003"}})
if err != nil {
panic(err)
}
println("res: %v\n", resp)
println("succ!")
}
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package impl
import (
"reflect"
"strings"
)
import (
hessian "github.com/apache/dubbo-go-hessian2"
)
import (
"github.com/apache/dubbo-go/common/constant"
"github.com/apache/dubbo-go/common/extension"
"github.com/apache/dubbo-go/filter"
"github.com/apache/dubbo-go/protocol"
invocation2 "github.com/apache/dubbo-go/protocol/invocation"
)
const (
GENERIC = "generic"
)
func init() {
extension.SetFilter(GENERIC, GetGenericFilter)
}
// when do a generic invoke, struct need to be map
type GenericFilter struct{}
func (ef *GenericFilter) Invoke(invoker protocol.Invoker, invocation protocol.Invocation) protocol.Result {
if invocation.MethodName() == constant.GENERIC && len(invocation.Arguments()) == 3 {
oldArguments := invocation.Arguments()
var newParams []hessian.Object
if oldParams, ok := oldArguments[2].([]interface{}); ok {
for i := range oldParams {
newParams = append(newParams, hessian.Object(struct2MapAll(oldParams[i])))
}
} else {
return invoker.Invoke(invocation)
}
newArguments := []interface{}{
oldArguments[0],
oldArguments[1],
newParams,
}
newInvocation := invocation2.NewRPCInvocation(invocation.MethodName(), newArguments, invocation.Attachments())
newInvocation.SetReply(invocation.Reply())
return invoker.Invoke(newInvocation)
}
return invoker.Invoke(invocation)
}
func (ef *GenericFilter) OnResponse(result protocol.Result, invoker protocol.Invoker, invocation protocol.Invocation) protocol.Result {
return result
}
func GetGenericFilter() filter.Filter {
return &GenericFilter{}
}
func struct2MapAll(obj interface{}) interface{} {
if obj == nil {
return obj
}
t := reflect.TypeOf(obj)
v := reflect.ValueOf(obj)
if t.Kind() == reflect.Struct {
result := make(map[string]interface{}, t.NumField())
for i := 0; i < t.NumField(); i++ {
if v.Field(i).Kind() == reflect.Struct {
if v.Field(i).CanInterface() {
setInMap(result, t.Field(i), struct2MapAll(v.Field(i).Interface()))
}
} else if v.Field(i).Kind() == reflect.Slice {
if v.Field(i).CanInterface() {
setInMap(result, t.Field(i), struct2MapAll(v.Field(i).Interface()))
}
} else {
if v.Field(i).CanInterface() {
setInMap(result, t.Field(i), v.Field(i).Interface())
}
}
}
return result
} else if t.Kind() == reflect.Slice {
value := reflect.ValueOf(obj)
var newTemps = make([]interface{}, 0, value.Len())
for i := 0; i < value.Len(); i++ {
newTemp := struct2MapAll(value.Index(i).Interface())
newTemps = append(newTemps, newTemp)
}
return newTemps
} else {
return obj
}
}
func setInMap(m map[string]interface{}, structField reflect.StructField, value interface{}) (result map[string]interface{}) {
result = m
if tagName := structField.Tag.Get("m"); tagName == "" {
result[headerAtoa(structField.Name)] = value
} else {
result[tagName] = value
}
return
}
func headerAtoa(a string) (b string) {
b = strings.ToLower(a[:1]) + a[1:]
return
}
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package impl
import (
"reflect"
"testing"
)
import (
"github.com/stretchr/testify/assert"
)
func Test_struct2MapAll(t *testing.T) {
var testData struct {
AaAa string `m:"aaAa"`
BaBa string
CaCa struct {
AaAa string
BaBa string `m:"baBa"`
XxYy struct {
xxXx string `m:"xxXx"`
Xx string `m:"xx"`
} `m:"xxYy"`
} `m:"caCa"`
}
testData.AaAa = "1"
testData.BaBa = "1"
testData.CaCa.BaBa = "2"
testData.CaCa.AaAa = "2"
testData.CaCa.XxYy.xxXx = "3"
testData.CaCa.XxYy.Xx = "3"
m := struct2MapAll(testData).(map[string]interface{})
assert.Equal(t, "1", m["aaAa"].(string))
assert.Equal(t, "1", m["baBa"].(string))
assert.Equal(t, "2", m["caCa"].(map[string]interface{})["aaAa"].(string))
assert.Equal(t, "3", m["caCa"].(map[string]interface{})["xxYy"].(map[string]interface{})["xx"].(string))
assert.Equal(t, reflect.Map, reflect.TypeOf(m["caCa"]).Kind())
assert.Equal(t, reflect.Map, reflect.TypeOf(m["caCa"].(map[string]interface{})["xxYy"]).Kind())
}
type testStruct struct {
AaAa string
BaBa string `m:"baBa"`
XxYy struct {
xxXx string `m:"xxXx"`
Xx string `m:"xx"`
} `m:"xxYy"`
}
func Test_struct2MapAll_Slice(t *testing.T) {
var testData struct {
AaAa string `m:"aaAa"`
BaBa string
CaCa []testStruct `m:"caCa"`
}
testData.AaAa = "1"
testData.BaBa = "1"
var tmp testStruct
tmp.BaBa = "2"
tmp.AaAa = "2"
tmp.XxYy.xxXx = "3"
tmp.XxYy.Xx = "3"
testData.CaCa = append(testData.CaCa, tmp)
m := struct2MapAll(testData).(map[string]interface{})
assert.Equal(t, "1", m["aaAa"].(string))
assert.Equal(t, "1", m["baBa"].(string))
assert.Equal(t, "2", m["caCa"].([]interface{})[0].(map[string]interface{})["aaAa"].(string))
assert.Equal(t, "3", m["caCa"].([]interface{})[0].(map[string]interface{})["xxYy"].(map[string]interface{})["xx"].(string))
assert.Equal(t, reflect.Slice, reflect.TypeOf(m["caCa"]).Kind())
assert.Equal(t, reflect.Map, reflect.TypeOf(m["caCa"].([]interface{})[0].(map[string]interface{})["xxYy"]).Kind())
}
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment