0

我的代码遇到了障碍,希望有人能提供帮助。

我有一个正在构建的应用程序,我被迫使用 Java 并将其部署到 Glassfish 3.1 服务器。这不是我通常喜欢的工作方式,因为我更像是一名 Python 开发人员。因此,我已经使用 Jython 2.7,并且正在使用 Flask。

但是,我正在使用 Blueprints 图形 DB API 的 Bitsy 实现来构建一个图形,该图形表示我的应用程序将在基于 REST 的 API(源自 Oracle DB,使用 JPA 2.0)中提供的数据。

我已经成功地使用以下代码构建了我的图表:

from __future__ import division, absolute_import, print_function

import collections
import java.lang.Class
import java.lang.Runtime
import java.nio.file.Paths
import os
import tempfile

import concurrent.futures
from flask import Flask

import contextlib2 as contextlib
import javax.persistence.Persistence as JPA

import com.lambdazen.bitsy.BitsyGraph

import java.lang.management.ManagementFactory

app = Flask(__name__.split('.')[0])

def process_indi(pool, graph, parent_key, indi_key):
    """
    Processes a single indicator to be loaded on the graph.
    """
    indi_class = java.lang.Class.forName("pampas.db.r.models.Indi")
    manager_factory = JPA.createEntityManagerFactory("pampas-r")
    manager = manager_factory.createEntityManager()
    try:
        indi = manager.createNamedQuery('Indi.findByIndiKey', indi_class)
        indi = indi.setParameter("indi_key", indi_key)
        indi = indi.singleResult
        trans = graph.newTransaction()
        try:
            vert = trans.addVertex(None)

            vert.setProperty('indi_key', indi.cidIndicatorKey)

            if indi_key == 'SYSTEM_ROOT':
                region_class = java.lang.Class.forName("pampas.db.r.models.Region")
                region = manager.createNamedQuery('Region.findThis', region_class)
                region = region.singleResult
                vert.setProperty('name', region.cidRegion)

                status_text_class = java.lang.Class.forName("pampas.db.r.models.StatusText")
                status_text = manager.createNamedQuery('StatusText.findAll', status_text_class)
                states = {
                    state.cidStatus: state.ctxDesc
                    for state in status_text.resultList
                }
                vert.setProperty('states', states)
            else:
                vert.setProperty('name', indi.ctxDesc)

                states = {
                    threshold.id.nnoStatus: threshold.ctxDesc
                    for threshold in indi.thresholds
                }
                if states:
                    vert.setProperty('states', states)

            if indi.ctxTooltip is not None:
                vert.setProperty('tooltip', indi.ctxTooltip)
            if indi.ctxHyperlink is not None:
                vert.setProperty('link', indi.ctxHyperlink)

            with contextlib.suppress(AttributeError):
                vert.setProperty('status', indi.script.statusText.cidStatus)
                vert.setProperty('last_updated', indi.script.dtCurrent)

            with contextlib.suppress(AttributeError):
                if indi.vSuppressActives.size() > 0:
                    for suppress in indi.vSuppressActives:
                        print(suppress.ctxComment)
                    vert.setProperty('suppressed', True)

            with contextlib.suppress(AttributeError):
                key_value = False
                edit_list = False
                for plugin_value in indi.pluginValues:
                    if plugin_value.pluginGroup.ctxEditType == 'KEY_VALUE':
                        key_value = True
                    elif plugin_value.pluginGroup.ctxEditType == 'LIST':
                        edit_list = True

                    if key_value and edit_list:
                        break

                if key_value:
                    vert.setProperty('key_value', key_value)
                if edit_list:
                    vert.setProperty('edit_list', edit_list)

            if parent_key is not None:
                parent = None
                for item in trans.getVertices('indi_key', indi.parent.cidIndicatorKey):
                    parent = item
                    break
                trans.addEdge(None, vert, parent, 'ancestor')
                print('{parent} => {child}'.format(
                    parent=parent.getProperty('name'), child=vert.getProperty('name')))
            else:
                print(vert.getProperty('name'))
        finally:
            trans.commit()

        futures = tuple(
            pool.submit(process_indi, pool, graph, vert, child.cidIndicatorKey)
            for child in indi.children
        )
    finally:
        manager.close()

    return futures


@app.route('/gen_tree')
def gen_tree():
    """
    Generate the tree and load it into the Bitsy (Blueprints) GraphDB.
    """
    db_path = os.path.join(tempfile.gettempdir(), 'pampas', 'graph')
    with contextlib.suppress(OSError):
        os.makedirs(db_path)
    db_path = java.nio.file.Paths.get(db_path)
    graph = com.lambdazen.bitsy.BitsyGraph(db_path)

    vertex_class = java.lang.Class.forName("com.tinkerpop.blueprints.Vertex")
    try:
        trans = graph.newTransaction()
        try:
            trans.createKeyIndex('indi_key', vertex_class)
            trans.createKeyIndex('suppressed', vertex_class)
        finally:
            trans.commit()

        futures = collections.deque()
        runtime = java.lang.Runtime.getRuntime()
        cpu_count = runtime.availableProcessors()
        with concurrent.futures.ThreadPoolExecutor(cpu_count * 5) as pool:
            batch = process_indi(pool, graph, None, 'SYSTEM_ROOT')
            if batch:
                futures.append(batch)

            while futures:
                block = futures.popleft()
                for future in concurrent.futures.as_completed(block):
                    batch = future.result()
                    if batch:
                        futures.append(batch)
                print('Num Vertices:', len(tuple(graph.getVertices())), '| Num Edges:', len(tuple(graph.getEdges())))

    finally:
        graph.shutdown()

    return 'Graph DB built.'

这很好用,并完全按照我的意愿生成我的图表。

但是,当我添加以下内容时:

import com.tinkerpop.blueprints.util.wrappers.readonly.ReadOnlyGraph

@app.route('/')
def read_tree():
    db_path = os.path.join(tempfile.gettempdir(), 'pampas', 'graph')
    with contextlib.suppress(OSError):
        os.makedirs(db_path)
    db_path = java.nio.file.Paths.get(db_path)
    graph = com.lambdazen.bitsy.BitsyGraph(db_path)
    rograph = com.tinkerpop.blueprints.util.wrappers.readonly.ReadOnlyGraph(graph)
    root = None
    for node in rograph.getVertices('indi_key', 'SYSTEM_ROOT'):
        root = node
        break
    return root.getProperty('name')

我尝试运行这段代码(从http://localhost:8080/data/基于其他配置),我得到以下信息:

2016-08-31T11:02:06.745-0400|Info: PWC1412: WebModule[null] ServletContext.log():debug: Attempting to import application callable 'wsgi.application'

2016-08-31T11:02:06.746-0400|Info: PWC1412: WebModule[null] ServletContext.log():debug: Application is <Flask 'pampas'>
2016-08-31T11:02:06.862-0400|Warning: StandardWrapperValve[modjy]: PWC1406: Servlet.service() for servlet modjy threw exception
com.lambdazen.bitsy.BitsyException: INSTANCE_ALREADY_EXISTS: A BitsyGraph object with the same path has been registered with the MBeanServer. Creating multiple instances of BitsyGraph (without calling shutdown) will cause data corruption. Path C:\Users\QTB0065\AppData\Local\Temp\pampas\graph
    at com.lambdazen.bitsy.BitsyGraph.<init>(BitsyGraph.java:91)
    at com.lambdazen.bitsy.BitsyGraph.<init>(BitsyGraph.java:63)
    at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
    at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:57)
    at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
    at java.lang.reflect.Constructor.newInstance(Constructor.java:526)
    at org.python.core.PyReflectedConstructor.constructProxy(PyReflectedConstructor.java:211)
    at org.python.core.PyReflectedConstructor.__call__(PyReflectedConstructor.java:180)
    at org.python.core.PyObject.__call__(PyObject.java:419)
    at org.python.core.PyMethod.instancemethod___call__(PyMethod.java:237)
    at org.python.core.PyMethod.__call__(PyMethod.java:228)
    at org.python.core.PyMethod.__call__(PyMethod.java:223)
    at org.python.core.Deriveds.dispatch__init__(Deriveds.java:19)
    at org.python.core.PyObjectDerived.dispatch__init__(PyObjectDerived.java:1112)
    at org.python.core.PyType.type___call__(PyType.java:1713)
    at org.python.core.PyType.__call__(PyType.java:1696)
    at org.python.core.PyObject.__call__(PyObject.java:461)
    at org.python.core.PyObject.__call__(PyObject.java:465)
    at pampas.test$py.read_tree$1(C:\Users\QTB0065\Apps\glassfish3\glassfish\domains\pampas\applications\pampas-be\pampas\test.py:74)
    at pampas.test$py.call_function(C:\Users\QTB0065\Apps\glassfish3\glassfish\domains\pampas\applications\pampas-be\pampas\test.py)
    at org.python.core.PyTableCode.call(PyTableCode.java:167)
    at org.python.core.PyBaseCode.call(PyBaseCode.java:307)
    at org.python.core.PyFunction.function___call__(PyFunction.java:471)
    at org.python.core.PyFunction.__call__(PyFunction.java:466)
    at org.python.core.PyFunction.__call__(PyFunction.java:461)
    at org.python.core.PyObject._callextra(PyObject.java:601)
    at flask.app$py.dispatch_request$69(C:\Users\QTB0065\AppData\Local\Temp\pip-build-bmhjzf\flask\flask\app.py:1625)
    at flask.app$py.call_function(C:\Users\QTB0065\AppData\Local\Temp\pip-build-bmhjzf\flask\flask\app.py)
    at org.python.core.PyTableCode.call(PyTableCode.java:167)
    at org.python.core.PyBaseCode.call(PyBaseCode.java:138)
    at org.python.core.PyFunction.__call__(PyFunction.java:413)
    at org.python.core.PyMethod.__call__(PyMethod.java:126)
    at flask.app$py.full_dispatch_request$70(C:\Users\QTB0065\AppData\Local\Temp\pip-build-bmhjzf\flask\flask\app.py:1645)
    at flask.app$py.call_function(C:\Users\QTB0065\AppData\Local\Temp\pip-build-bmhjzf\flask\flask\app.py)
    at org.python.core.PyTableCode.call(PyTableCode.java:167)
    at org.python.core.PyBaseCode.call(PyBaseCode.java:138)
    at org.python.core.PyFunction.__call__(PyFunction.java:413)
    at org.python.core.PyMethod.__call__(PyMethod.java:126)
    at flask.app$py.wsgi_app$85(C:\Users\QTB0065\AppData\Local\Temp\pip-build-bmhjzf\flask\flask\app.py:1996)
    at flask.app$py.call_function(C:\Users\QTB0065\AppData\Local\Temp\pip-build-bmhjzf\flask\flask\app.py)
    at org.python.core.PyTableCode.call(PyTableCode.java:167)
    at org.python.core.PyBaseCode.call(PyBaseCode.java:170)
    at org.python.core.PyFunction.__call__(PyFunction.java:434)
    at org.python.core.PyMethod.__call__(PyMethod.java:156)
    at flask.app$py.__call__$86(C:\Users\QTB0065\AppData\Local\Temp\pip-build-bmhjzf\flask\flask\app.py:2000)
    at flask.app$py.call_function(C:\Users\QTB0065\AppData\Local\Temp\pip-build-bmhjzf\flask\flask\app.py)
    at org.python.core.PyTableCode.call(PyTableCode.java:167)
    at org.python.core.PyBaseCode.call(PyBaseCode.java:170)
    at org.python.core.PyFunction.__call__(PyFunction.java:434)
    at org.python.core.PyMethod.__call__(PyMethod.java:156)
    at modjy.modjy$py.call_application$10(C:\Users\QTB0065\Apps\glassfish3\glassfish\domains\pampas\applications\pampas-be\WEB-INF\lib\jython.jar\Lib\modjy\modjy.py:109)
    at modjy.modjy$py.call_function(C:\Users\QTB0065\Apps\glassfish3\glassfish\domains\pampas\applications\pampas-be\WEB-INF\lib\jython.jar\Lib\modjy\modjy.py)
    at org.python.core.PyTableCode.call(PyTableCode.java:167)
    at org.python.core.PyBaseCode.call(PyBaseCode.java:188)
    at org.python.core.PyFunction.__call__(PyFunction.java:446)
    at org.python.core.PyMethod.__call__(PyMethod.java:171)
    at modjy.modjy$py.dispatch_to_application$9(C:\Users\QTB0065\Apps\glassfish3\glassfish\domains\pampas\applications\pampas-be\WEB-INF\lib\jython.jar\Lib\modjy\modjy.py:103)
    at modjy.modjy$py.call_function(C:\Users\QTB0065\Apps\glassfish3\glassfish\domains\pampas\applications\pampas-be\WEB-INF\lib\jython.jar\Lib\modjy\modjy.py)
    at org.python.core.PyTableCode.call(PyTableCode.java:167)
    at org.python.core.PyBaseCode.call(PyBaseCode.java:188)
    at org.python.core.PyFunction.__call__(PyFunction.java:446)
    at org.python.core.PyMethod.__call__(PyMethod.java:171)
    at modjy.modjy$py.service$7(C:\Users\QTB0065\Apps\glassfish3\glassfish\domains\pampas\applications\pampas-be\WEB-INF\lib\jython.jar\Lib\modjy\modjy.py:80)
    at modjy.modjy$py.call_function(C:\Users\QTB0065\Apps\glassfish3\glassfish\domains\pampas\applications\pampas-be\WEB-INF\lib\jython.jar\Lib\modjy\modjy.py)
    at org.python.core.PyTableCode.call(PyTableCode.java:167)
    at org.python.core.PyBaseCode.call(PyBaseCode.java:307)
    at org.python.core.PyBaseCode.call(PyBaseCode.java:198)
    at org.python.core.PyFunction.__call__(PyFunction.java:482)
    at org.python.core.PyMethod.instancemethod___call__(PyMethod.java:237)
    at org.python.core.PyMethod.__call__(PyMethod.java:228)
    at org.python.core.PyMethod.__call__(PyMethod.java:218)
    at org.python.core.PyMethod.__call__(PyMethod.java:213)
    at org.python.core.PyObject._jcallexc(PyObject.java:3626)
    at org.python.proxies.modjy.modjy$modjy_servlet$0.service(Unknown Source)
    at com.xhaus.modjy.ModjyJServlet.service(ModjyJServlet.java:142)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:770)
    at org.apache.catalina.core.StandardWrapper.service(StandardWrapper.java:1550)
    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:281)
    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:175)
    at org.apache.catalina.core.StandardPipeline.doInvoke(StandardPipeline.java:655)
    at org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.java:595)
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:161)
    at org.apache.catalina.connector.CoyoteAdapter.doService(CoyoteAdapter.java:331)
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:231)
    at com.sun.enterprise.v3.services.impl.ContainerMapper$AdapterCallable.call(ContainerMapper.java:317)
    at com.sun.enterprise.v3.services.impl.ContainerMapper.service(ContainerMapper.java:195)
    at com.sun.grizzly.http.ProcessorTask.invokeAdapter(ProcessorTask.java:860)
    at com.sun.grizzly.http.ProcessorTask.doProcess(ProcessorTask.java:757)
    at com.sun.grizzly.http.ProcessorTask.process(ProcessorTask.java:1056)
    at com.sun.grizzly.http.DefaultProtocolFilter.execute(DefaultProtocolFilter.java:229)
    at com.sun.grizzly.DefaultProtocolChain.executeProtocolFilter(DefaultProtocolChain.java:137)
    at com.sun.grizzly.DefaultProtocolChain.execute(DefaultProtocolChain.java:104)
    at com.sun.grizzly.DefaultProtocolChain.execute(DefaultProtocolChain.java:90)
    at com.sun.grizzly.http.HttpProtocolChain.execute(HttpProtocolChain.java:79)
    at com.sun.grizzly.ProtocolChainContextTask.doCall(ProtocolChainContextTask.java:54)
    at com.sun.grizzly.SelectionKeyContextTask.call(SelectionKeyContextTask.java:59)
    at com.sun.grizzly.ContextTask.run(ContextTask.java:71)
    at com.sun.grizzly.util.AbstractThreadPool$Worker.doWork(AbstractThreadPool.java:532)
    at com.sun.grizzly.util.AbstractThreadPool$Worker.run(AbstractThreadPool.java:513)
    at java.lang.Thread.run(Thread.java:745)

特别感兴趣的是:

com.lambdazen.bitsy.BitsyException:INSTANCE_ALREADY_EXISTS:具有相同路径的 BitsyGraph 对象已向 MBeanServer 注册。创建多个 BitsyGraph 实例(不调用 shutdown)将导致数据损坏。路径 C:\Users\QTB0065\AppData\Local\Temp\pampas\graph

这显然是因为我会生成我的图表,然后尝试从同一服务器上的另一个 url ("servlet" [sic]) 读取它。如果我已经注册了一个 BitsyGraph 对象,并且它存在,有什么方法可以将该实例从一个“servlet”传递到另一个?

4

1 回答 1

0

好的,所以我找到了解决方案,并且因为没有意识到这一点而感到非常愚蠢。为了使它工作,我需要在应用程序上下文中创建我的图形对象,然后我可以在任何地方使用它。

with app.app_context():
    db_path = os.path.join(tempfile.gettempdir(), 'pampas', 'graph')
    with contextlib.suppress(OSError):
        os.makedirs(db_path)
    db_path = java.nio.file.Paths.get(db_path)
    flask.current_app.graph = com.lambdazen.bitsy.BitsyGraph(db_path)

然后我可以在我需要的每个例程中使用相同的图形对象,并且错误不存在。

于 2016-09-01T13:28:15.197 回答