apache / incubator-hugegraph-toolchain

HugeGraph toolchain - include a series useful graph modules
https://hugegraph.apache.org/
Apache License 2.0
88 stars 92 forks source link

[Feature] Constraint hubble and server create a partial exception to the connection process #586

Closed returnToInnocence closed 6 months ago

returnToInnocence commented 6 months ago

Search before asking

Feature Description (功能描述)

Are you willing to submit a PR?

Code of Conduct

dosubot[bot] commented 6 months ago

Sure, I'd be happy to guide you through the process of submitting a PR for this feature. Here are the steps you need to follow:

  1. Fork and Clone the Repository: First, you need to fork the HugeGraph repository on GitHub and clone your fork to your local machine. You can do this with the following commands:

    git clone https://github.com/${GITHUB_USER_NAME}/hugegraph
  2. Configure Your Local Repository: Next, set up your local repository with your GitHub user name and email. You can do this with the following commands:

    cd hugegraph
    git remote add hugegraph https://github.com/apache/hugegraph
    git config user.name "{full-name}"
    git config user.email "{email-address-of-github}"
  3. Create a New Branch: It's best not to use the master branch for development. Instead, create a new branch for your feature. You can do this with the following commands:

    git checkout master
    git pull hugegraph
    git checkout -b feature-branch
  4. Make Your Changes: Now you can start implementing your feature. Make sure to modify the relevant files, such as those within the hugegraph-core/src/main/java/org/apache/hugegraph/ directory or specific to your feature.

  5. Commit Your Changes: After you've made your changes, add them to your local repository and commit them with a meaningful message. You can do this with the following commands:

    git add .
    git commit -m "Implement feature to constrain exception messages in /api/v1.2/graph-connections"
  6. Push Your Changes: Next, push your changes to your fork on GitHub. You can do this with the following commands:

    git push origin feature-branch:feature-branch
  7. Create a Pull Request (PR): Now go to your fork on GitHub and initiate a pull request from your feature branch to the main HugeGraph repository. Make sure to fill in the PR description with details of the changes you are proposing.

  8. Code Review: Wait for the maintainers to review your PR. If they have any feedback, make further changes and push them to your branch. Your PR will be updated automatically.

  9. Further Changes and Conflict Resolution: If necessary, make further changes based on the review feedback. If there are conflicts, you may need to rebase your branch on the latest master and resolve the conflicts. You can do this with the following commands:

    git checkout master
    git pull hugegraph
    git checkout feature-branch
    git rebase -i master
  10. Final Steps: Push your changes again if necessary. Once all checks pass and your changes are approved by the maintainers, your PR will be merged into the main codebase.

Please remember to check the contribution guidelines of the project for any additional requirements or steps. You can find them here.

As for the current behavior of the /api/v1.2/graph-connections post request when it encounters partial exceptions, it's not explicitly detailed in the provided code snippet. However, we can infer that when partial exceptions occur (e.g., validation failure, unauthorized access, connection test failure), the method is designed to halt the operation and throw an ExternalException. The specific behavior (e.g., error message, HTTP status code) would depend on how these exceptions are handled at a higher level in the application, which is not shown in the provided code snippet.

The current structure of the error messages returned by the /api/v1.2/graph-connections POST request when it encounters partial exceptions is likely to include a specific error code or message key indicating the type of error and parameters or values related to the error context. However, without seeing the implementation of the ExternalException class or how the application translates these keys into actual error messages, it's not possible to provide the exact structure of the error messages.

I hope this helps! If you have any other questions, feel free to ask.

Sources

#### About Dosu This response is meant to be useful and save you time. It is **not meant to be a precise solution**, but rather a starting point for your own research. Help me be more useful! Please leave a 👍 if this is helpful and 👎 if it is irrelevant. If you want to continue the conversation, start your reply with @dosu-bot.
dosubot[bot] commented 6 months ago

The tryConnect method in the HugeClientUtil.java file is currently a static method. Changing it from a static type to a public instance method could have several potential impacts, both advantages and disadvantages.

Advantages

  1. Object-Oriented Design: Making tryConnect a non-static method allows it to be part of an object's behavior. This aligns with object-oriented principles where data and behavior are encapsulated together, enabling more cohesive and modular code design.

  2. Statefulness and Configurability: As a public instance method, tryConnect can access instance variables of the HugeClientUtil class, allowing it to use or modify the state of its containing object. This can be useful for maintaining state or configuration settings specific to a HugeClientUtil instance.

  3. Subclassing and Overriding: If HugeClientUtil were to be subclassed, having tryConnect as an instance method would allow subclasses to override this method to provide specialized behavior for different types of connections or error handling strategies.

Disadvantages

  1. Increased Complexity for Simple Use Cases: For use cases where tryConnect simply needs to create and return a HugeClient without needing any state or configuration from a HugeClientUtil instance, making it an instance method adds unnecessary complexity. Users of the method would need to instantiate HugeClientUtil before calling tryConnect, which is an extra step compared to calling a static method directly.

  2. Resource Management: If tryConnect relies on instance variables or resources, each HugeClientUtil instance may consume more memory or resources. In contrast, a static method would not inherently consume instance-specific resources.

  3. Concurrency Considerations: If tryConnect modifies instance state, there could be concurrency issues if multiple threads are using the same HugeClientUtil instance. Proper synchronization would be necessary to avoid inconsistent states. This is less of a concern with a static method, especially if it doesn't rely on shared state.

  4. Testing and Mocking: Testing instance methods can be slightly more cumbersome than static methods since you need to instantiate the class. Additionally, mocking static methods (for example, with frameworks like Mockito) requires additional setup (e.g., using the mockito-inline artifact) compared to instance methods, which are straightforward to mock.

In summary, changing tryConnect from static to public instance method could enhance object-oriented design and flexibility at the cost of increased complexity and potential resource management issues. The decision should be based on the specific needs of the application and how HugeClientUtil is used within it.

As for the current functionality of the tryConnect method, it attempts to establish a connection to a HugeGraph database using the provided GraphConnection details. It constructs the URL, handles authentication, configures the client, handles various exceptions, tests the connection with a Gremlin query, validates the existence of the graph, and returns the configured HugeClient instance if all steps are successful.

The tryConnect method is currently declared with the public access modifier, which means it is already accessible to other classes in the same package and subclasses in other packages. Changing it from static to non-static would not affect its visibility.

You can find more details about the tryConnect method in the HugeClientUtil.java file.

Sources

#### About Dosu This response is meant to be useful and save you time. It is **not meant to be a precise solution**, but rather a starting point for your own research. Help me be more useful! Please leave a 👍 if this is helpful and 👎 if it is irrelevant. If you want to continue the conversation, start your reply with @dosu-bot.
dosubot[bot] commented 6 months ago

To encapsulate the ServerException results caught in the tryConnect method in the HugeClientUtil.java file using the ExternalException.java file or other methods to uniformly encapsulate the message and cause, while considering the need to hide the details of the interface and desensitize error information, you can follow these steps:

  1. Create a Generic ExternalException Handler: Define a method that takes a ServerException and converts it into an ExternalException, ensuring that the error message is desensitized and does not expose sensitive information about the backend or the nature of the error directly.

  2. Use Descriptive but Generic Error Messages: Instead of directly passing the error message from the ServerException, use predefined, generic error messages that describe the nature of the error without revealing sensitive details.

  3. Log Detailed Errors for Internal Use: While you desensitize the error information for the client, it's important to log the detailed error messages internally for debugging purposes.

Here's how you could implement these steps in your HugeClientUtil.java:

// Step 1: Generic ExternalException Handler Method
private static void handleServerException(ServerException e, String graph, String host, Integer port) {
    String message = e.getMessage();
    if (Constant.STATUS_UNAUTHORIZED == e.status()) {
        throw new ExternalException("graph-connection.username-or-password.incorrect", e);
    } else if (message != null && message.contains("Could not rebind [g]")) {
        throw new ExternalException("graph-connection.graph.unexist", e, graph, host, port);
    } else if (!isAcceptable(message)) {
        // Step 2: Use a generic error message
        throw new ExternalException("server.error.generic", e);
    }
    // Optionally log the detailed error message internally
    // Logger.error("ServerException encountered: " + message);
}

// Modify the catch block for ServerException in the tryConnect method to use this handler
try {
    ResultSet rs = client.gremlin().gremlin("g.V().limit(1)").execute();
    rs.iterator().forEachRemaining(Result::getObject);
} catch (ServerException e) {
    handleServerException(e, graph, host, port); // Use the handler method
} catch (Exception e) {
    client.close();
    throw e;
}

In this approach, the handleServerException method acts as a centralized place to handle ServerException instances. It uses predefined error codes like "graph-connection.username-or-password.incorrect" and "graph-connection.graph.unexist" for specific known errors, and a generic "server.error.generic" code for other cases. This method can be expanded to include more specific error handling as needed, while keeping the error messages exposed to clients generic and desensitized.

This approach should help you encapsulate the ServerException results and hide the details of the interface and desensitize error information. If you have any further questions or need more clarification, feel free to ask.

Sources

#### About Dosu This response is meant to be useful and save you time. It is **not meant to be a precise solution**, but rather a starting point for your own research. Help me be more useful! Please leave a 👍 if this is helpful and 👎 if it is irrelevant. If you want to continue the conversation, start your reply with @dosu-bot.
dosubot[bot] commented 6 months ago

In the context of the tryConnect method in the HugeClientUtil.java file, when a ServerException is caught and an ExternalException is thrown with the error code "server.error.generic", the appropriate message and cause for this exception should be as follows:

The message should be a user-friendly description of the error that occurred. This message is intended to be displayed to the end user and should be clear and concise. It should provide enough information for the user to understand what went wrong, but it should not include any sensitive information or details that would be irrelevant or confusing to the user. For example, the message could be something like "An error occurred while trying to connect to the server."

The cause for the ExternalException should be the original ServerException that was caught. This allows the full stack trace of the original exception to be preserved and can provide valuable debugging information. The cause can be set when constructing the ExternalException by passing it as a parameter to the constructor, like this:

throw new ExternalException("server.error.generic", serverException);

In this case, "server.error.generic" is the error code that will be associated with the ExternalException, and serverException is the original ServerException that was caught.

Please note that the actual error code and message should be chosen based on the specific circumstances of the error. The error code "server.error.generic" and the message "An error occurred while trying to connect to the server." are just examples and may not be appropriate for all situations.

For more information on how to handle exceptions in HugeGraph, you can refer to the HugeGraph documentation, specifically the section on Error Handling.

I hope this helps! If you have any further questions, please don't hesitate to ask.

Source Code

Sources

#### About Dosu This response is meant to be useful and save you time. It is **not meant to be a precise solution**, but rather a starting point for your own research. Help me be more useful! Please leave a 👍 if this is helpful and 👎 if it is irrelevant. If you want to continue the conversation, start your reply with @dosu-bot.
dosubot[bot] commented 6 months ago

The HugeClientUtil.java file in the HugeGraph Hubble project uses the definitions from the messages.properties file primarily for internationalization (i18n) and localization. This properties file contains key-value pairs where the key is a unique identifier for a specific message, and the value is the message itself, possibly with placeholders for dynamic content. These messages can be error messages, information messages, or any text content that needs to be internationalized.

Java's ResourceBundle class is typically used to load these properties files and retrieve the values based on the keys. The values retrieved from the messages.properties file can then be used within the application to display messages to the user in their language, assuming there are corresponding translations for those keys in other properties files for specific locales (e.g., messages_fr.properties for French).

When HugeClientUtil.java needs to display a message, it would look up the message key in the messages.properties file and use the corresponding value. If the message contains placeholders (e.g., {0}, {1}), these placeholders can be dynamically replaced with specific values at runtime. This approach allows for messages that are adaptable to different contexts within the application while keeping the code clean from hard-coded strings.

For example, if there's an error related to a version mismatch between the hugegraph-client and hugegraph-server, the HugeClientUtil.java might use the key client-server.version.unmatched to retrieve and display the message "The version of hugegraph-client and hugegraph-server don't match" to the user. If the application needs to support multiple languages, developers can provide translations of this message in separate properties files for each supported language.

Unfortunately, I wasn't able to find the specific methods in HugeClientUtil.java that are responsible for retrieving and using the messages from the messages.properties file, nor the exact path of the HugeClientUtil.java file in the incubator-hugegraph-toolchain repository. If you could provide more details or context, I might be able to give a more precise answer.

You can find more information about the messages.properties file in the hugegraph-hubble/hubble-be/src/main/resources/i18n/messages.properties path in the repository.

Sources

#### About Dosu This response is meant to be useful and save you time. It is **not meant to be a precise solution**, but rather a starting point for your own research. Help me be more useful! Please leave a 👍 if this is helpful and 👎 if it is irrelevant. If you want to continue the conversation, start your reply with @dosu-bot.
dosubot[bot] commented 6 months ago

The HugeClientUtil.java file in the HugeGraph Hubble project uses the service.suspected-web parameter from the messages.properties file to handle a specific type of connection error. When the error message from a ClientException contains the string <!doctype html>, it suggests that the server is not a HugeGraph server but rather a web server. In this case, an ExternalException is thrown with the service.suspected-web parameter as the error code. Here is the relevant code snippet:

} catch (ClientException e) {
    Throwable cause = e.getCause();
    if (cause == null || cause.getMessage() == null) {
        throw e;
    }
    String message = cause.getMessage();
    if (message.contains("Connection refused")) {
        throw new ExternalException("service.unavailable", e, host, port);
    } else if (message.contains("java.net.UnknownHostException") ||
               message.contains("Host name may not be null")) {
        throw new ExternalException("service.unknown-host", e, host);
    } else if (message.contains("<!doctype html>")) {
        throw new ExternalException("service.suspected-web",
                                    e, host, port);
    }
    throw e;
}

This code block is designed to handle different types of connection errors by throwing an ExternalException with a specific error code that can be localized using the messages.properties file. The service.suspected-web parameter is used as the error code when the response from the server is an HTML document, which is not expected for a HugeGraph server connection.

You can find the HugeClientUtil.java file in the HugeGraph Hubble project here.

The messages.properties file is a properties file that contains key-value pairs, where each key represents a specific message identifier and the value is the message text itself. This file is used for internationalization (i18n) purposes, allowing the application to support messages in multiple languages easily by defining them in separate properties files. The service.suspected-web parameter is one of the keys in this file.

You can find the messages.properties file in the HugeGraph Hubble project here.

I hope this answers your question. If you need further clarification, feel free to ask.

Sources

#### About Dosu This response is meant to be useful and save you time. It is **not meant to be a precise solution**, but rather a starting point for your own research. Help me be more useful! Please leave a 👍 if this is helpful and 👎 if it is irrelevant. If you want to continue the conversation, start your reply with @dosu-bot.
dosubot[bot] commented 6 months ago

To use the service.suspected-web parameter from the messages.properties file in the ExceptionAdvisor.java file, you can use the ResourceBundle class in Java. This class provides a mechanism to read properties files.

Here's a step-by-step guide:

  1. Load the messages.properties file using the ResourceBundle.getBundle() method. You need to specify the base name of the bundle. If your project is correctly set up to use the default locale and file encoding, you can simply use the base name without specifying the locale or file encoding explicitly.

  2. Retrieve the value of service.suspected-web using the getString() method of the ResourceBundle instance.

Here's a code snippet that demonstrates these steps:

import java.util.ResourceBundle;

public class ExceptionAdvisor {
    public void someMethod() {
        // Assuming the default locale and UTF-8 encoding
        ResourceBundle messages = ResourceBundle.getBundle("i18n/messages");

        // Retrieve the 'service.suspected-web' message
        String suspectedWebMessage = messages.getString("service.suspected-web");

        // Now you can use the message, for example, logging or throwing an exception
        System.out.println(suspectedWebMessage);
    }
}

This example assumes that the messages.properties file is located in a directory that is in the classpath and follows the convention for ResourceBundle (i.e., i18n/messages corresponds to i18n/messages.properties in the src/main/resources directory). Adjust the path according to your project structure if necessary.

As for the structure of the messages.properties file, it starts with a license header under the Apache License, Version 2.0. Following the license header, there are comments and property key-value pairs. The property keys are categorized into several sections, including but not limited to: External Exceptions, Common utility messages, Client-server version mismatch messages, Service availability messages, Graph connection messages, Graph vertex and edge messages, Gremlin execution messages, Execute history messages, Schema-related messages, Load-related messages, Job manager messages, Internal Exceptions. Each property key is prefixed with a category (e.g., common., client-server., service., graph-connection., graph., gremlin., execute-history., schema., load., job.manager., common.unknown.enum.type, entity., execute., reflect., license., https.) indicating its usage context. The values for these keys are messages, often with placeholders for dynamic content (e.g., {0}, {1}) to be replaced at runtime. The file uses the standard .properties format, which is a simple key-value pair format used in Java properties files.

You can find the messages.properties file in the incubator-hugegraph-toolchain repository.

Sources

#### About Dosu This response is meant to be useful and save you time. It is **not meant to be a precise solution**, but rather a starting point for your own research. Help me be more useful! Please leave a 👍 if this is helpful and 👎 if it is irrelevant. If you want to continue the conversation, start your reply with @dosu-bot.