Giter Site home page Giter Site logo

ravendb-jvm-client's Introduction

RavenDB - An ACID NoSQL Document Database

This repository contains source code for the RavenDB document database. With a RavenDB database you can set up a NoSQL data architecture or add a NoSQL layer to your current relational database.

RavenDB Studio

Supported Platforms

  • Windows
  • Linux
  • Docker
  • MacOS
  • Raspberry Pi

Grab Your License and Download Latest Version

Request your license.

Download the latest version of RavenDB.

Getting Started

Install and set up your database.

Learn RavenDB Quickly

RavenDB Bootcamp is a free, self-directed learning course. In just three units you will learn how to use RavenDB to create fully-functional, real-world programs with NoSQL Databases. If you are unfamiliar with NoSQL, it’s okay. We will provide you with all the information you need.

Stay Updated on New Developments

We keep adding new features to improve your RavenDB experience. Check out our latest improvements, updated weekly.

Documentation

Access full documentation for RavenDB. Like our database, it is easy to use.

Where to Ask for Help

If you have any questions, or need further assistance, you can contact us directly.

Report an Issue

Please check where to report an issue in our contribution guidelines.

RavenDB Developer Community Group

If you have any questions please visit our discussions page or check Google community group archive. The solutions for the most common challenges are available. You are welcome to join!

Pull Requests

Please check how to submit a Pull Request in our contribution guidelines.

Setup & Run

First please review and set up prerequisites.

Launch RavenDB:

Running locally:

<path/to/ravendb>/Server/Raven.Server

Registering as service in Windows using rvn utility available in the package Server directory:

<path\to\ravendb>\rvn.exe windows-service register --service-name RavenDB4

Hello World (.NET)

Server Side

  • Launch a RavenDB server instance as follows:
<path/to/ravendb>/Server/Raven.Server --ServerUrl=http://localhost:8080
  • Open a web browser and enter http://localhost:8080

  • Click on Databases in the menu on the left-hand side, and then create a new database named SampleDataDB

  • Click on Settings and then on Create Sample Data in the left menu. Now Click on Create

Client Side

mkdir HelloWorld
cd HelloWorld
dotnet new console
  • Add the RavenDB Client package:
   dotnet add package RavenDB.Client --version 6.0.0-*
  • Replace the content of Program.cs with the following:
using System;
using Raven.Client.Documents;

namespace HelloWorld
{
    class Shippers
    {
        public string Name;
        public string Phone;
    }
    
    class Program
    {
        static void Main(string[] args)
        {
            using (var store = new DocumentStore
            {
                Urls = new string[] {"http://localhost:8080"},
                Database = "SampleDataDB"
            })
            {
                store.Initialize();

                using (var session = store.OpenSession())
                {
                    var shipper = session.Load<Shippers>("shippers/1-A");
                    Console.WriteLine("Shipper #1 : " + shipper.Name + ", Phone: " + shipper.Phone);
                }
            }
        }
    }
}
  • Type:
dotnet restore
dotnet build
dotnet run

SAST Tools

Enjoy :)

ravendb-jvm-client's People

Contributors

apatrida avatar damccull avatar dependabot[bot] avatar gregolsky avatar johannesrudolph avatar ml054 avatar vijayakumarsuraj avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

ravendb-jvm-client's Issues

Manually set up test server?

Hello. I'm trying to run the test suite on my local machine but I'm running under WSL, so no .exe exists to run in RAVENDB_JAVA_TEST_SERVER_PATH. Is there a way to skip that step and just run it against a server I manually set up and already have running?

Scala support

Currently RavenDB requires Java beans which makes it hard to work with Scala.
I'm not sure if there are any plans for supporting Scala, but would you be willing to accept PRs making JVM client more extensible?

Something that would make it possible to inject your own json serializer/deserializer would be a good start though.

Can't Use UUID Field as Identifier (even though a uuid can be a string)

Hi,

I think I've found a few bugs regarding setting the Identifier field.

https://ravendb.net/docs/article-page/5.4/java/server/kb/document-identifier-generation#guid shows that Guid (the C# version of a UUID) can be generated, but doesn't give an example of how to use it. The documentation for the java equivalent (UUID) seems to be missing entirely.

https://ravendb.net/docs/article-page/5.4/csharp/client-api/document-identifiers/working-with-document-identifiers says that identifiers are always strings, but you must have C# selected. This same documentation should be provided if you have Java selected, but when java is selected nothing is shown.  (I found this by ggoogling)

So combining these two, I would think there's a way to use a java.util.UUID field as the identifier (and if there isn't, I would strongly encourage implementing this in order to be compatible with existing (legacy) data models). UUID fields can be converted to strings (toString()) and made from strings (UUID.fromString(value)) so it wouldn't be difficult to implement if it does indeed only exist on the C# side, but not the java side. Jackson ObjectMpapers automatically recognize UUIDs for serialization and deserialization

Serialize -- put just the UUID back in to the field to send back to the user

Pattern UUID_REGEX =
  Pattern.compile("^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$");
(if field with @id or that is set as IdentifierField is of type UUID) {
 String potentialUuid = jsonNodeValue.substring([identityPartsSeparator} + 1)
    if (potentialUUID.matches()) {
         // set the field to UUID.fromString(potentialUUID)
     )  // throw an error
}

Call a UUID generator in the store() and set it on the UUID field so that the user has it immediately

Deserialize -- make the id compatible for use internally `

(if field with @id or that is set as IdentifierField is of type UUID) {
    // set it object.getSimpleName() + identityPartsSeparator + jsonNodeValue.toString()
}

Add a DocumentStore.Builder

Hi,

Would you be amenable to modifying the DocumentStore to use the Builder pattern? It has several advantages. The biggest are that it's self documenting (quite a few of the method javadocs seem to be missing) and that business logic of what can be called before certain points in time vs later are hidden from the user. The user would know what the absolutely required params are, i.e. just the url and database (which is checked for in the assertValidConfiguration I believe) because they are required in the constructor. That would also make it clear that certain methods must be called at "building" time, i.e. before initialize since after some deprecation period setters would only be available through the builder. In fact, initialize() would be called from the build() so the user wouldn't need to know. As it is now, users have to quasi understand your business logic flow instead of just needing to know how to configure the DocumentStore once and from then on use it to get sessions. (Also, internally you could stop relying on assertions that the store has been initialized because the only way to get a store ti through the builder, which would initialize it) In short, I'm proposing adding to the code so that a DocumentStore is built (and initialized) like this

 DocumentStore store = new DocumentStore.Builder(urls, database)
      .setCertficiate(cert)
      .setPrivateKeyPassword(password)
      .setTruststore(truststore
     .setConventions(new DocumentConventions.Builder().setUseOptomisticLocking(true).build())
     .build();

This would return a DocumentStore ready to call openSession (i.e. already initalized). This pattern wold be more intuitive to jvm language programmers, as it's what's used for mongo and others.

I would be willing to do the work (addition of code and tests) and submit a PR, but wanted to know if it would be a welcome addition. In the long term, I wouldn't remove the existing access to the setters and constructors, but I would mark them as Deprecated. That way, you can decide when you want to make change, as it would be a breaking change (but one that most usres would accept and appreciate) I'd love to help start a spring-data-ravendb community project, which would really need this sort of change first. Having a driver that conforms more to standard jvm language practices would make it easier for users to consider adopting RavenDB,.

Data subscriptions throw an IllegalStateException: "Session can only be opened once per each Subscription batch"

I am opening a single session per batch, but it looks like the batch object that is yielded to my subscriber is the same instance each time (just containing the next set of items).

In the c# client, SubscriptionBatch.InitializeAsync resets the _sessionOpened flag to false - which allows the subscriber to open a session against each new batch. The Java client doesn't seem to be doing this.

I am using v6.0 (of client and server).

Error from subscription: `Server returned illegal type message when expecting connection status, was:ERROR`

Seeing this error at pretty regular intervals from my subscription.

java.lang.IllegalStateException: Server returned illegal type message when expecting connection status, was:ERROR
	at net.ravendb.client.documents.subscriptions.SubscriptionWorker.assertConnectionState(SubscriptionWorker.java:337)
	at net.ravendb.client.documents.subscriptions.SubscriptionWorker.processSubscription(SubscriptionWorker.java:416)
	at net.ravendb.client.documents.subscriptions.SubscriptionWorker.lambda$runSubscriptionAsync$4(SubscriptionWorker.java:586)
	at java.base/java.util.concurrent.CompletableFuture$AsyncRun.run(CompletableFuture.java:1736)
	at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128)
	at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628)
	at java.base/java.lang.Thread.run(Thread.java:829)

After some more digging, I can see the actual error that the server sent back was:

Raven.Server.Rachis.RachisApplyException: Can't update subscription with name 'values/kwl-sales-db/subscriptions/LegacyPurchaseMigrator' by node B, because it's not it's task to update this subscription
   at Raven.Server.ServerWide.Commands.Subscriptions.UpdateSubscriptionClientConnectionTime.GetUpdatedValue(Int64 index, RawDatabaseRecord record, JsonOperationContext context, BlittableJsonReaderObject existingValue) in C:\Builds\RavenDB-Stable-5.3\53004\src\Raven.Server\ServerWide\Commands\Subscriptions\UpdateSubscriptionClientConnectionTime.cs:line 38
   at Raven.Server.ServerWide.Commands.UpdateValueForDatabaseCommand.Execute(ClusterOperationContext context, Table items, Int64 index, RawDatabaseRecord record, RachisState state, Object& result) in C:\Builds\RavenDB-Stable-5.3\53004\src\Raven.Server\ServerWide\Commands\UpdateValueForDatabaseCommand.cs:line 54
   at Raven.Server.ServerWide.ClusterStateMachine.SetValueForTypedDatabaseCommand(ClusterOperationContext context, String type, BlittableJsonReaderObject cmd, Int64 index, Leader leader, Object& result) in C:\Builds\RavenDB-Stable-5.3\53004\src\Raven.Server\ServerWide\ClusterStateMachine.cs:line 1397
   at Raven.Server.ServerWide.ClusterStateMachine.Apply(ClusterOperationContext context, BlittableJsonReaderObject cmd, Int64 index, Leader leader, ServerStore serverStore) in C:\Builds\RavenDB-Stable-5.3\53004\src\Raven.Server\ServerWide\ClusterStateMachine.cs:line 707
--- End of stack trace from previous location ---
   at Raven.Server.Rachis.Leader.PutAsync(CommandBase command, TimeSpan timeout) in C:\Builds\RavenDB-Stable-5.3\53004\src\Raven.Server\Rachis\Leader.cs:line 691
   at Raven.Server.ServerWide.ServerStore.SendToLeaderAsyncInternal(TransactionOperationContext context, CommandBase cmd) in C:\Builds\RavenDB-Stable-5.3\53004\src\Raven.Server\ServerWide\ServerStore.cs:line 2930
   at Raven.Server.ServerWide.ServerStore.SendToLeaderAsyncInternal(CommandBase cmd) in C:\Builds\RavenDB-Stable-5.3\53004\src\Raven.Server\ServerWide\ServerStore.cs:line 2915
   at Raven.Server.ServerWide.ServerStore.SendToLeaderAsync(CommandBase cmd) in C:\Builds\RavenDB-Stable-5.3\53004\src\Raven.Server\ServerWide\ServerStore.cs:line 2749
   at Raven.Server.Documents.Subscriptions.SubscriptionStorage.UpdateClientConnectionTime(Int64 id, String name, String mentorNode) in C:\Builds\RavenDB-Stable-5.3\53004\src\Raven.Server\Documents\Subscriptions\SubscriptionStorage.cs:line 176
   at Raven.Server.Documents.TcpHandlers.SubscriptionConnection.NotifyClientAboutSuccess(Int64 registerConnectionDurationInTicks) in C:\Builds\RavenDB-Stable-5.3\53004\src\Raven.Server\Documents\TcpHandlers\SubscriptionConnection.cs:line 238
   at Raven.Server.Documents.TcpHandlers.SubscriptionConnection.Run(TcpConnectionOptions tcpConnectionOptions, IDisposable subscriptionConnectionInProgress) in C:\Builds\RavenDB-Stable-5.3\53004\src\Raven.Server\Documents\TcpHandlers\SubscriptionConnection.cs:line 402

The client re-connects and the subscription continues. But it does appear like this shouldn't be happening as part of normal operation?

I am on v5.2.2 of the client. This error was coming from our production cluster that has 3 nodes.

Suggestion: More Intuitive Way to Specify Identifier Property

Hi,

I think I've found a few bugs regarding setting the Identifer field.

I can specify a function that returns a non-string field to be used as the Identifier when I use findIdentifierProperty. There are no checks on the function that I provide. In the code below, I tried to say I wanted to use a UUID field type as the identifier (something that is somewhat documented for C#, but not for java -- will submit a different issue ticket for this)

Code to reproduce (Using Junit 5 and Spring)

@Configuration
public class TestRavenConfig extends RavenTestDriver {

  // This allows us to modify the conventions of the store we get from 'getDocumentStore'
  @Override
  protected void preInitialize(IDocumentStore documentStore) {
     documentStore.getConventions() .setFindIdentityProperty(
             property -> property.getPropertyType().isAssignableFrom(UUID.class));
  }

  @Bean
  public IDocumentStore documentStore() {
    return getDocumentStore();
  }

  @Bean
  public SessionOptions sessionOptions() {
    SessionOptions sessionOptions = new SessionOptions();
    sessionOptions.setTransactionMode(TransactionMode.SINGLE_NODE);
    sessionOptions.setDatabase(documentStore().getDatabase());
    return sessionOptions;
  }

Test Code

@SpringBootTest(classes = TestRavenConfig.class)
@ExtendWith(SpringExtension.class)
public class OrderRepositoryTest {

  private @Autowired DocumentStore store;
  private @Autowired SessionOptions options;

  Logger logger = LoggerFactory.getLogger(OrderRepositoryTest.class);

  @Test
  public void save() {

    Order testOrder = new Order();
    IDocumentSession session = store.openSession(options);
    session.store(testOrder);
    session.saveChanges();

    [logger.info](http://logger.info/)("===================================================");
    [logger.info](http://logger.info/)("uuid: ", testOrder.getUuid());
    [logger.info](http://logger.info/)("====================================================");

    session.close();
    store.close();
  }

Output

2023-03-06T17:14:29.178Z  INFO 12542 --- [    Test worker] net.ravendb.embedded.EmbeddedServer      : Starting global server
    2023-03-06T17:14:33.007Z  INFO 12542 --- [    Test worker] d.k.a.repository.OrderRepositoryTest     : Started OrderRepositoryTest in 5.376 seconds (process running for 10.649)

OrderRepositoryTest > save() FAILED
    java.lang.IllegalArgumentException: Cannot set identity value 'orders/1-A' on field class java.util.UUID because field type is not string.
        at net.ravendb.client.documents.identity.GenerateEntityIdOnTheClient.setPropertyOrField(GenerateEntityIdOnTheClient.java:116)
        at net.ravendb.client.documents.identity.GenerateEntityIdOnTheClient.trySetIdentityInternal(GenerateEntityIdOnTheClient.java:108)
        at net.ravendb.client.documents.identity.GenerateEntityIdOnTheClient.trySetIdentity(GenerateEntityIdOnTheClient.java:88)
        at net.ravendb.client.documents.identity.GenerateEntityIdOnTheClient.trySetIdentity(GenerateEntityIdOnTheClient.java:78)
        at net.ravendb.client.documents.identity.GenerateEntityIdOnTheClient.generateDocumentKeyForStorage(GenerateEntityIdOnTheClient.java:73)
        at net.ravendb.client.documents.session.InMemoryDocumentSessionOperations.storeInternal(InMemoryDocumentSessionOperations.java:830)
        at net.ravendb.client.documents.session.InMemoryDocumentSessionOperations.store(InMemoryDocumentSessionOperations.java:786)
  net.ravendb.embedded.EmbeddedServer      : Try shutdown server gracefully.

I think the heart of the issue is that you're asking the user to know your business logic. They have to know that you're using a Function to inspect property fields (why not have them tell you the field name and you do the function), and at the time that they have to know that the Function must return a String field. I propose the following to address the above situation:

  1. Deprecate findIdentityProperty. Requiring the user to pass in a function exposes a lot of your business logic to the user and honestly isn't very intuitive.
  2. Replace it with one or both of the following (both hide that you're using Functions while letting the user know that only String fields are appropriate):
    • (Preferred as it is idiomatic to what other databases do) Implement an @RavenId annotation that the user would simply annotate the desired field with. That makes it clear to the user when they look at their model class which field is being used as the Id. When store() is called, check that one and only one String field is annotated and return an error if the annotated field isn't a String, if there's no annotation AND no field named "Id", or if more than one field is annotated with @id (unless you support compound ids). Behind the scenes, set the property name of the annotated field as the argument to the function.
      I'm not saying RavenDB should always do what other databases do, but there are some conventions for some common tasks, like identifier specification are petty much expected.
      Examples from other databases
      https://mongodb.github.io/mongo-java-driver/3.7/javadoc/?org/bson/codecs/pojo/annotations/BsonId.html
      https://docs.spring.io/spring-data/neo4j/docs/current/api/org/springframework/data/neo4j/core/schema/Id.html

    • (less clear to the user when they are looking at thier own model) Make a setIdentifierField(String fieldName) method and have the user pass in the name of their identifier field. When store() is called, check that the object has a field with the specified name and that it's a string. Behind the scenes, set the property name of the annotated field as the argument to the function.

Both suggestions wouldn't require major changes to the underlying code -- you would just make the Function for the user. In both suggestions, in the store() method

     if (!knownTypesSet.contains(obj) {
          // do checks. 
          // make/set Function
          // add obj type to the set
     }

Cancelled Operations do not raise OperationCancelledExceptions

There appears to be a typo in the code. The status returned by the server is:

{"$type":"Raven.Client.Documents.Operations.OperationState, Raven.Client","Progress":null,"Result":null,"Status":"Canceled"}

but the case has one l too many:

                case "Cancelled":
                    throw new OperationCancelledException();

I think this should be caught by a unit test or something.

Kotlin deserialization - SOLVED

Certain Kotlin classes will fail to deserialize, for example one without an empty constructor:

class Doctor(var name: String)

The solution is to set the store's entity mapper to one that understands Kotlin.
For example:

import com.fasterxml.jackson.databind.DeserializationFeature
import com.fasterxml.jackson.module.kotlin.jacksonObjectMapper
import net.ravendb.client.documents.DocumentStore
import net.ravendb.client.documents.IDocumentStore

class Doctor(var name: String)

val mapper = jacksonObjectMapper().apply {
    configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false)
}

 val store: IDocumentStore = .... 
store.conventions.entityMapper = mapper
store.initialize()

Note: the FAIL_ON_UNKNOWN_PROPERTIES configuration is to prevent failure with the document's @metadata property.

NOTE: the setEntityMapper appears to be undocumented, ie: a search of the RavenDB site for 'mapper' returns no hits.

waitForIndexesAfterSaveChanges() calls wrong overload?

I was just browsing the source to figure out something, and noticed this:

    public void waitForIndexesAfterSaveChanges() {
        waitForReplicationAfterSaveChanges(options -> {
        });
    }

from:

Shouldn't this call into public void waitForIndexesAfterSaveChanges(Consumer<InMemoryDocumentSessionOperations.IndexesWaitOptsBuilder> options) instead?

Looks like a copy/paste error to me.

Comment documentation welcome?

As I'm reading through the library source and learning how it works, I'm adding comments to sections of code as well as javadoc comments to methods and classes. This is for me to help understand the code without forgetting how it works, creating easy reminders for myself.

Would the devs be interested in pull requests adding javadoc comments like this? https://github.com/damccull/ravendb-jvm-client/blob/documentation/src/main/java/net/ravendb/client/http/RequestExecutor.java#L281-L294

How about embedded comments within the code that explain the reason and/or workings behind sections of code that aren't obvious? I don't have any examples showing this at the moment, but I'm asking as a separate question so that I can tailor my commits and branches according to the preferred PRs, should this be something that'd be welcomed.

RavenTestDriver: EINVAL when opening /tmp/

After fighting to get .net core 2.1.5 installed to run RavenTestDriver, running a plain RavenTestDriver.getDocumentStore() greets me with this exception:

12:26:22.048 [main] INFO  net.ravendb.embedded.EmbeddedServer - Starting global server

java.lang.IllegalStateException: Unable to start the RavenDB Server
Output:
       _____                       _____  ____ 
      |  __ \                     |  __ \|  _ \ 
      | |__) |__ ___   _____ _ __ | |  | | |_) |
      |  _  // _` \ \ / / _ \ '_ \| |  | |  _ < 
      | | \ \ (_| |\ V /  __/ | | | |__| | |_) |
      |_|  \_\__,_| \_/ \___|_| |_|_____/|____/ 


      Safe by default, optimized for efficiency

 Build 41010, Version 4.1, SemVer 4.1.4, Commit dc2e9e3
 PID 25343, 64 bits, 12 Cores, Phys Mem 31.293 GBytes, Arch: X64
 Source Code (git repo): https://github.com/ravendb/ravendb
 Built with love by Hibernating Rhinos and awesome contributors!
+---------------------------------------------------------------+


Raven.Client.Exceptions.Server.ServerLoadFailureException: Failed to load system storage 
At /tmp/1551871581612-1/System ---> System.InvalidOperationException: EINVAL when opening /tmp/1551871581612-1/System/Journals/0000000000000000000.journal

This is running on Fedora28. My /tmp is a tmpfs.

I then wanted to run a custom configuration to see whether putting the data dir on another filesystem will help. So I put up a nice

    val testServerOptions = ServerOptions().apply {
      // specify where ravendb server should be extracted (optional)
      targetServerLocation = "/tmp/x-ravendb"
      dataDirectory = "/tmp/x-ravendb/data"
    }

    configureServer(testServerOptions)

but to no effect. Why? Well...

    public static void configureServer(ServerOptions options) {
        if (TEST_SERVER_STORE.isValueCreated()) {
            throw new IllegalStateException("Cannot configure server after it was started. " +
                    "Please call 'configureServer' method before any 'getDocumentStore' is called.");
        }
    }

Apparently, configureServer doesn't do anything. It should probably set the serverOptions supplier...

Sorry guys, but the first time experience I had with running RavenTestdriver has been absolutely horrendous so far. In order:

  • fix NPEs around dotnet not being installed #14
  • any way to make the ravendb-test-driver compatible with any .net 2.x or at least 2.1.x release? 2.1.5 is old, current is 2.1.8 and that forces me to through incantations with my package manager to get it installed
  • the EINVAL looks scarry and has no hints on what to fix
  • configureServer should... work?

Non blocking client for Java

I am scoping out this client's documentation and RavenDB's website and I do not see any mention of a non-blocking or reactive client.

Is this a feature of this client ? Or maybe another one ?

Should Throw Error When No ID Field Exists/Is Specified

Hi,

I think I've found a few bugs regarding setting the Identifer field.

If your model object does not have have a Id field, and you have not set a different field to be used as the Id by calling findIdentifierProperty you don't get an error when you store the object.

In the sample code below, the Order object does NOT have an Id field. It has a uuid field, but I haven't called findIdentifierProperty. I should get an error when session.store() is calleld but I don't.

Code (Using Junit5 with Spring)
The Configuration (Setup)

@Configuration
public class TestRavenConfig extends RavenTestDriver {

  @Bean
  public IDocumentStore documentStore() {
    return getDocumentStore();
  }

  @Bean
  public SessionOptions sessionOptions() {
    SessionOptions sessionOptions = new SessionOptions();
    sessionOptions.setTransactionMode(TransactionMode.SINGLE_NODE);
    sessionOptions.setDatabase(documentStore().getDatabase());
    return sessionOptions;
  }

The Test

@SpringBootTest(classes = TestRavenConfig.class)
@ExtendWith(SpringExtension.class)
public class OrderRepositoryTest {

  private @Autowired DocumentStore store;
  private @Autowired SessionOptions options;

  Logger logger = LoggerFactory.getLogger(OrderRepositoryTest.class);

  @Test
  public void save() {

    Order testOrder = new Order();
    IDocumentSession session = store.openSession(options);
    session.store(testOrder);
    session.saveChanges();

    [logger.info](http://logger.info/)("===================================================");
    [logger.info](http://logger.info/)("uuid: ", testOrder.getUuid());
    [logger.info](http://logger.info/)("====================================================");

    session.close();
    store.close();
  }

The output -- no error is ever thrown and my uuid field (which I understand RavenDB doesn't know is what I want to use as an Id) is still null. I made sure that errors were NOT hidden by my logging level. If I had any assertions in this test, it would fail. The point is, I think this scenario should throw an error, otherwise in actual non-test code I might think everything is ok.

2023-03-06T17:08:28.379Z  INFO 11725 --- [    Test worker] net.ravendb.embedded.EmbeddedServer      : Starting global server
    2023-03-06T17:08:32.103Z  INFO 11725 --- [    Test worker] d.k.a.repository.OrderRepositoryTest     : Started OrderRepositoryTest in 5.303 seconds (process running for 10.288)

OrderRepositoryTest > save() STANDARD_OUT
    2023-03-06T17:08:32.342Z  INFO 11725 --- [    Test worker] d.k.a.repository.OrderRepositoryTest     : ===================================================
    2023-03-06T17:08:32.343Z  INFO 11725 --- [    Test worker] d.k.a.repository.OrderRepositoryTest     : uuid:
 ====================================================

OrderRepositoryTest > save() PASSED

SubscriptionWorker does not handle "redirects" correctly

Looks like the SubscriptionWorker isn't handling the REDIRECT connection status correctly. Seeing "Could not redirect to null, because it was not found in local topology, even after retrying" exceptions at regular intervals when consuming a data subscription.

A quick investigation led me to this line in the SubscriptionWorker as being the culprit. It'll make null RedirectTag values into the string "null". Which in turn causes shouldTryToReconnect to throw instead of returning true.

Connecting to RavenDB server using a self-signed certificate

I am experimenting with RavenDB and Java. My RavenDB is installed on a Ubuntu host using a self-signed certificate. Then I generate the client certificate using the management UI. After that I got a zip file, which I extracted and use it in the code like so:

var keystore = CertificateUtils.createKeystore(
        "path\\to\\app.crt",
        "path\\to\\app.key");

try (DocumentStore store = new DocumentStore(new String[]{HTTPS_ENDPOINT}, DATABASE)) {
    store.setCertificate(keystore);

    store.initialize();

    // do your work here
    var session = store.openSession();
    session.load(Object.class, DOCUMENT_ID);
}

However I got the following error:

22:04:25.925 [main] DEBUG org.apache.http.impl.conn.PoolingHttpClientConnectionManager - Connection released: [id: 1][route: {s}-><HTTPS_ENDPOINT>][total available: 0; route allocated: 0 of 30; total allocated: 0 of 40]
Exception in thread "main" net.ravendb.client.exceptions.RavenException: An exception occurred while contacting <HTTPS_ENDPOINT>/databases/<DATABASE>/docs?&id=<DOCUMENT_ID>.
javax.net.ssl.SSLHandshakeException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
The server at <HTTPS_ENDPOINT>/databases/<DATABASE>/docs?&id=<DOCUMENT_ID> responded with status code: 503
	at net.ravendb.client.exceptions.ExceptionDispatcher.get(ExceptionDispatcher.java:37)
	at net.ravendb.client.http.RequestExecutor.readExceptionFromServer(RequestExecutor.java:1579)
	at net.ravendb.client.http.RequestExecutor.handleServerDown(RequestExecutor.java:1253)
	at net.ravendb.client.http.RequestExecutor.sendRequestToServer(RequestExecutor.java:868)
	at net.ravendb.client.http.RequestExecutor.execute(RequestExecutor.java:726)
	at net.ravendb.client.http.RequestExecutor.execute(RequestExecutor.java:681)
	at net.ravendb.client.http.RequestExecutor.unlikelyExecute(RequestExecutor.java:484)
	at net.ravendb.client.http.RequestExecutor.execute(RequestExecutor.java:444)
	at net.ravendb.client.documents.session.DocumentSession.load(DocumentSession.java:340)
Caused by: javax.net.ssl.SSLHandshakeException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
	at java.base/sun.security.ssl.Alert.createSSLException(Alert.java:131)
	at java.base/sun.security.ssl.TransportContext.fatal(TransportContext.java:369)
	at java.base/sun.security.ssl.TransportContext.fatal(TransportContext.java:312)
	at java.base/sun.security.ssl.TransportContext.fatal(TransportContext.java:307)
	at java.base/sun.security.ssl.CertificateMessage$T13CertificateConsumer.checkServerCerts(CertificateMessage.java:1357)
	at java.base/sun.security.ssl.CertificateMessage$T13CertificateConsumer.onConsumeCertificate(CertificateMessage.java:1232)
	at java.base/sun.security.ssl.CertificateMessage$T13CertificateConsumer.consume(CertificateMessage.java:1175)
	at java.base/sun.security.ssl.SSLHandshake.consume(SSLHandshake.java:396)
	at java.base/sun.security.ssl.HandshakeContext.dispatch(HandshakeContext.java:480)
	at java.base/sun.security.ssl.HandshakeContext.dispatch(HandshakeContext.java:458)
	at java.base/sun.security.ssl.TransportContext.dispatch(TransportContext.java:199)
	at java.base/sun.security.ssl.SSLTransport.decode(SSLTransport.java:171)
	at java.base/sun.security.ssl.SSLSocketImpl.decode(SSLSocketImpl.java:1488)
	at java.base/sun.security.ssl.SSLSocketImpl.readHandshakeRecord(SSLSocketImpl.java:1394)
	at java.base/sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:441)
	at java.base/sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:412)
	at org.apache.http.conn.ssl.SSLConnectionSocketFactory.createLayeredSocket(SSLConnectionSocketFactory.java:436)
	at org.apache.http.conn.ssl.SSLConnectionSocketFactory.connectSocket(SSLConnectionSocketFactory.java:384)
	at org.apache.http.impl.conn.DefaultHttpClientConnectionOperator.connect(DefaultHttpClientConnectionOperator.java:142)
	at org.apache.http.impl.conn.PoolingHttpClientConnectionManager.connect(PoolingHttpClientConnectionManager.java:376)
	at org.apache.http.impl.execchain.MainClientExec.establishRoute(MainClientExec.java:393)
	at org.apache.http.impl.execchain.MainClientExec.execute(MainClientExec.java:236)
	at org.apache.http.impl.execchain.ProtocolExec.execute(ProtocolExec.java:186)
	at org.apache.http.impl.execchain.RetryExec.execute(RetryExec.java:89)
	at org.apache.http.impl.execchain.RedirectExec.execute(RedirectExec.java:110)
	at org.apache.http.impl.client.InternalHttpClient.doExecute(InternalHttpClient.java:185)
	at org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:83)
	at org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:108)
	at net.ravendb.client.http.RavenCommand.send(RavenCommand.java:115)
	at net.ravendb.client.http.RequestExecutor.send(RequestExecutor.java:882)
	at net.ravendb.client.http.RequestExecutor.sendRequestToServer(RequestExecutor.java:861)
	... 6 more
Caused by: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
	at java.base/sun.security.validator.PKIXValidator.doBuild(PKIXValidator.java:439)
	at java.base/sun.security.validator.PKIXValidator.engineValidate(PKIXValidator.java:306)
	at java.base/sun.security.validator.Validator.validate(Validator.java:264)
	at java.base/sun.security.ssl.X509TrustManagerImpl.checkTrusted(X509TrustManagerImpl.java:231)
	at java.base/sun.security.ssl.X509TrustManagerImpl.checkServerTrusted(X509TrustManagerImpl.java:132)
	at java.base/sun.security.ssl.CertificateMessage$T13CertificateConsumer.checkServerCerts(CertificateMessage.java:1341)
	... 32 more
Caused by: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
	at java.base/sun.security.provider.certpath.SunCertPathBuilder.build(SunCertPathBuilder.java:141)
	at java.base/sun.security.provider.certpath.SunCertPathBuilder.engineBuild(SunCertPathBuilder.java:126)
	at java.base/java.security.cert.CertPathBuilder.build(CertPathBuilder.java:297)
	at java.base/sun.security.validator.PKIXValidator.doBuild(PKIXValidator.java:434)
	... 37 more

I believe the SSLHandshakeException is caused because the client library failed to verify the server certificate which is self-signed.
Is there an option to skip the certificate verification?

BUG: TestDriver runtime version is lower than installed version but won't run

I'm trying to use the TestDriver in a junit test and I get the following error despite having version 7.0.3 of the .NET runtime installed which is above he require 6.0.9+ :

 Caused by:
                java.lang.IllegalStateException: Could not find a matching runtime for '6.0.9+'. Available runtimes:
                - 7.0.3
                    at net.ravendb.embedded.RuntimeFrameworkVersionMatcher.match(RuntimeFrameworkVersionMatcher.java:56)
                    at net.ravendb.embedded.RuntimeFrameworkVersionMatcher.match(RuntimeFrameworkVersionMatcher.java:28)
                    at net.ravendb.embedded.RavenServerRunner.run(RavenServerRunner.java:81)
                    at net.ravendb.embedded.EmbeddedServer.runServer(EmbeddedServer.java:187)
                    at net.ravendb.embedded.EmbeddedServer.lambda$startServer$0(EmbeddedServer.java:60)
                    at net.ravendb.client.documents.Lazy.getValue(Lazy.java:24)
                    at net.ravendb.embedded.EmbeddedServer.startServer(EmbeddedServer.java:71)
                    at net.ravendb.test.driver.RavenTestDriver.runServer(RavenTestDriver.java:358)
                    at net.ravendb.test.driver.RavenTestDriver.lambda$static$0(RavenTestDriver.java:61)
                    at net.ravendb.client.documents.Lazy.getValue(Lazy.java:24)
                    at net.ravendb.test.driver.RavenTestDriver.getDocumentStore(RavenTestDriver.java:116)
                    at net.ravendb.test.driver.RavenTestDriver.getDocumentStore(RavenTestDriver.java:101)

Do you need to update the test-driver package and re-release? RavenDB 5.4.100 itself (not the TestDriver which only goes up to 5.4) runs just fine on the above version of .NET.

Is there a TestContainers of RavenDB?

'Working with secured server' issue and resolution

I am connecting to our databases using SSL and was loading the certificate file as described under the section 'Working with secured server'. After a bunch of troubleshooting the best output I was able to get was this error:

javax.net.ssl.SSLHandshakeException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target

I don't know if this is always required, but in case anyone else runs into this problem I was able to fix it by exporting the certificate from Chrome using the option "Base64-encoded ASCII, certificate chain", and then importing this into Java's default keystore. I couldn't find this step documented anywhere. Thanks

Unable to find class by name in Quarkus CDI context - SOLVED

The following works in kotlin:

fun main(args: Array<String>) {
    val store: IDocumentStore = DocumentStore("http://localhost:8083", "test-db")
    store.initialize()

    store.openSession().apply {
        val d = Doctor()
        d.name = "dave"
        store(d, "1")
        saveChanges()
    }

    store.openSession().apply {
        val d = load(Doctor::class.java, "1")
        println(d.name)
    }

    store.close()
}

However, the exact same thing fails if called from a REST endpoint running in Quarkus:

Path("/doctors")
class DoctorResource {

    @GET
    @Path("/doctor")
    fun getDoctor(): Doctor? {

        val store: IDocumentStore = DocumentStore("http://localhost:8083", "test-db")
        store.initialize()

        store.openSession().apply {
            val d = Doctor()
            d.name = "dave"
            store(d, "1")
            saveChanges()
        }

        var d_from_db:Doctor? = null

        store.openSession().apply {
            d_from_db = load(Doctor::class.java, "1")
        }

        println(d_from_db)

        return d_from_db
    }

The error is as follows:

java.lang.IllegalStateException: Could not convert document 1 to entity of type au21.engine.framework.endpoints.Doctor
	at net.ravendb.client.documents.session.EntityToJson.convertToEntity(EntityToJson.java:178)
	at net.ravendb.client.documents.session.InMemoryDocumentSessionOperations.trackEntity(InMemoryDocumentSessionOperations.java:630)
	at net.ravendb.client.documents.session.InMemoryDocumentSessionOperations.trackEntity(InMemoryDocumentSessionOperations.java:574)
	at net.ravendb.client.documents.session.operations.LoadOperation.getDocument(LoadOperation.java:146)
	at net.ravendb.client.documents.session.operations.LoadOperation.getDocument(LoadOperation.java:132)
	at net.ravendb.client.documents.session.DocumentSession.load(DocumentSession.java:344)
	at au21.engine.framework.endpoints.DoctorResource.getDoctor(DoctorResource.kt:39)
	at au21.engine.framework.endpoints.DoctorResource_Subclass.getDoctor$$superaccessor1(DoctorResource_Subclass.zig:189)
	at au21.engine.framework.endpoints.DoctorResource_Subclass$$function$$4.apply(DoctorResource_Subclass$$function$$4.zig:29)
	at io.quarkus.arc.impl.AroundInvokeInvocationContext.proceed(AroundInvokeInvocationContext.java:54)
	at io.quarkus.arc.runtime.devconsole.InvocationInterceptor.proceed(InvocationInterceptor.java:62)
	at io.quarkus.arc.runtime.devconsole.InvocationInterceptor.monitor(InvocationInterceptor.java:49)
	at io.quarkus.arc.runtime.devconsole.InvocationInterceptor_Bean.intercept(InvocationInterceptor_Bean.zig:521)
	at io.quarkus.arc.impl.InterceptorInvocation.invoke(InterceptorInvocation.java:41)
	at io.quarkus.arc.impl.AroundInvokeInvocationContext.perform(AroundInvokeInvocationContext.java:41)
	at io.quarkus.arc.impl.InvocationContexts.performAroundInvoke(InvocationContexts.java:32)
	at au21.engine.framework.endpoints.DoctorResource_Subclass.getDoctor(DoctorResource_Subclass.zig:147)
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.base/java.lang.reflect.Method.invoke(Method.java:566)
	at org.jboss.resteasy.core.MethodInjectorImpl.invoke(MethodInjectorImpl.java:170)
	at org.jboss.resteasy.core.MethodInjectorImpl.invoke(MethodInjectorImpl.java:130)
	at org.jboss.resteasy.core.ResourceMethodInvoker.internalInvokeOnTarget(ResourceMethodInvoker.java:660)
	at org.jboss.resteasy.core.ResourceMethodInvoker.invokeOnTargetAfterFilter(ResourceMethodInvoker.java:524)
	at org.jboss.resteasy.core.ResourceMethodInvoker.lambda$invokeOnTarget$2(ResourceMethodInvoker.java:474)
	at org.jboss.resteasy.core.interception.jaxrs.PreMatchContainerRequestContext.filter(PreMatchContainerRequestContext.java:364)
	at org.jboss.resteasy.core.ResourceMethodInvoker.invokeOnTarget(ResourceMethodInvoker.java:476)
	at org.jboss.resteasy.core.ResourceMethodInvoker.invoke(ResourceMethodInvoker.java:434)
	at org.jboss.resteasy.core.ResourceMethodInvoker.invoke(ResourceMethodInvoker.java:408)
	at org.jboss.resteasy.core.ResourceMethodInvoker.invoke(ResourceMethodInvoker.java:69)
	at org.jboss.resteasy.core.SynchronousDispatcher.invoke(SynchronousDispatcher.java:492)
	at org.jboss.resteasy.core.SynchronousDispatcher.lambda$invoke$4(SynchronousDispatcher.java:261)
	at org.jboss.resteasy.core.SynchronousDispatcher.lambda$preprocess$0(SynchronousDispatcher.java:161)
	at org.jboss.resteasy.core.interception.jaxrs.PreMatchContainerRequestContext.filter(PreMatchContainerRequestContext.java:364)
	at org.jboss.resteasy.core.SynchronousDispatcher.preprocess(SynchronousDispatcher.java:164)
	at org.jboss.resteasy.core.SynchronousDispatcher.invoke(SynchronousDispatcher.java:247)
	at io.quarkus.resteasy.runtime.standalone.RequestDispatcher.service(RequestDispatcher.java:73)
	at io.quarkus.resteasy.runtime.standalone.VertxRequestHandler.dispatch(VertxRequestHandler.java:138)
	at io.quarkus.resteasy.runtime.standalone.VertxRequestHandler.access$000(VertxRequestHandler.java:41)
	at io.quarkus.resteasy.runtime.standalone.VertxRequestHandler$1.run(VertxRequestHandler.java:93)
	at io.quarkus.runtime.CleanableExecutor$CleaningRunnable.run(CleanableExecutor.java:231)
	at java.base/java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:515)
	at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:264)
	at org.jboss.threads.EnhancedQueueExecutor$Task.run(EnhancedQueueExecutor.java:2415)
	at org.jboss.threads.EnhancedQueueExecutor$ThreadBody.run(EnhancedQueueExecutor.java:1452)
	at org.jboss.threads.DelegatingRunnable.run(DelegatingRunnable.java:29)
	at org.jboss.threads.ThreadLocalResettingRunnable.run(ThreadLocalResettingRunnable.java:29)
	at java.base/java.lang.Thread.run(Thread.java:829)
	at org.jboss.threads.JBossThread.run(JBossThread.java:501)
Caused by: net.ravendb.client.exceptions.RavenException: Unable to find class by name = au21.engine.framework.endpoints.Doctor
	at net.ravendb.client.documents.conventions.DocumentConventions.lambda$new$4(DocumentConventions.java:168)
	at net.ravendb.client.documents.conventions.DocumentConventions.getJavaClassByName(DocumentConventions.java:645)
	at net.ravendb.client.documents.session.EntityToJson.convertToEntity(EntityToJson.java:157)
	... 49 more
Caused by: java.lang.ClassNotFoundException: au21.engine.framework.endpoints.Doctor
	at java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.java:581)
	at java.base/jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(ClassLoaders.java:178)
	at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:522)
	at io.quarkus.bootstrap.classloading.QuarkusClassLoader.loadClass(QuarkusClassLoader.java:421)
	at io.quarkus.bootstrap.classloading.QuarkusClassLoader.loadClass(QuarkusClassLoader.java:371)
	at java.base/java.lang.Class.forName0(Native Method)
	at java.base/java.lang.Class.forName(Class.java:315)
	at net.ravendb.client.documents.conventions.DocumentConventions.lambda$new$4(DocumentConventions.java:166)
	... 51 more
null

Error during use a certificate for store data

Expected Behavior

Store a new document into Raven.

Current Behavior

Exception while try to use the certificate .pfx generated.

Unable to find certificate for alias: '1'. If you generated certificate using RavenDB server, then it might be related to: https://github.com/dotnet/corefx/issues/30946. Please try to create Keystore using *.crt and *.key files instead of *.pfx.

Steps to Reproduce

The same found on wiki was used.

// load certificate
KeyStore clientStore = KeyStore.getInstance("PKCS12");
clientStore.load(new FileInputStream("c:\\ravendb\\client-cert.pfx"), "passwordToPfx".toCharArray());

try (DocumentStore store = new DocumentStore())  {
    store.setCertificate(clientStore);
    store.setDatabase("Northwind");
    store.setUrls(new String[]{ "https://my_secured_raven" });

    store.initialize();

    // do your work here
}

Context (Environment)

Windows 10
Spring Boot 2.2.6
OpenJDK 8

NullPointerException in RavenServerRunner.run

I tried the `RavenTestDriver' with the example from the docs and was immediately greated by an NPE.

The culprit appears to be L:93 processBuilder.directory().getAbsolutePath() as .directory() returns null.
The source annotation for ProcessBuilder.directory notes

    /**
     * Returns this process builder's working directory.
     *
     * Subprocesses subsequently started by this object's {@link
     * #start()} method will use this as their working directory.
     * The returned value may be {@code null} -- this means to use
     * the working directory of the current Java process, usually the
     * directory named by the system property {@code user.dir},
     * as the working directory of the child process.
     *
     * @return this process builder's working directory
     */

The exception handling code should thus handle null correctly, it's a pity not to see the original error because the exception handler throws an NPE...

StackOverflowError in data subscriptions when RavenDB server becomes unhealthy

The stacktrace is essentially

...
at net.ravendb.client.http.RequestExecutor.send(RequestExecutor.java:890)
at net.ravendb.client.http.RequestExecutor.sendRequestToServer(RequestExecutor.java:869)
at net.ravendb.client.http.RequestExecutor.execute(RequestExecutor.java:735)
at net.ravendb.client.http.RequestExecutor.execute(RequestExecutor.java:686)
at net.ravendb.client.http.RequestExecutor.handleServerDown(RequestExecutor.java:1337)
at net.ravendb.client.http.RequestExecutor.sendRequestToServer(RequestExecutor.java:876)
at net.ravendb.client.http.RequestExecutor.execute(RequestExecutor.java:735)
at net.ravendb.client.http.RequestExecutor.execute(RequestExecutor.java:686)
at net.ravendb.client.http.RequestExecutor.handleServerDown(RequestExecutor.java:1337)
at net.ravendb.client.http.RequestExecutor.sendRequestToServer(RequestExecutor.java:876)
at net.ravendb.client.http.RequestExecutor.execute(RequestExecutor.java:735)
at net.ravendb.client.http.RequestExecutor.execute(RequestExecutor.java:686)
at net.ravendb.client.http.RequestExecutor.handleServerDown(RequestExecutor.java:1337)
at net.ravendb.client.http.RequestExecutor.sendRequestToServer(RequestExecutor.java:876)
...

We're using the v5.4.0 client sdk, and the server is v5.4.109.

How persist Map<String, Object>?

In RavenDB is there any convention to I persist a Map instead of an entity?

   try (IDocumentSession session = documentStore.openSession()) {
           Map<String, Object> map = new HashMap<>();
           map.put("collection", "Person");
            map.put("age", 23);
            map.put("name", "Ada Lovelace");
            map.put("subdocument", Collections.singletonMap("doc", "map"));

            session.store(map);
}

NullPointerException from SubscriptionWorker

Calling addOnUnexpectedSubscriptionError on a SubscriptionWorker throws a NullPointerException because the onUnexpectedSubscriptionError field is never initialized.

Because of this any unexpected errors encountered by the worker also end-up throwing a NullPointerException (when EventHelper.invoke(onUnexpectedSubscriptionError, ex) is called).

I'm on JDK 11 using v5.2.1 of the ravendb client.

LocalDate and LocalDateTime serialization problem

Hello,
we use java.time.LocalDate and java.time.LocalDateTime structures for Date(Time) representation in our projects and when storing into RavenDB we just realized , that it is serialized into non-date structure as below. Is there a way how to instruct serializer to do it correctly so RavenDB can understand it as DateTime?

Example LocalDateTime serialized into RavenDB data record:

 "dateStart": {
        "hour": 9,
        "minute": 27,
        "nano": 436000000,
        "second": 15,
        "dayOfMonth": 17,
        "dayOfWeek": "MONDAY",
        "dayOfYear": 260,
        "month": "SEPTEMBER",
        "monthValue": 9,
        "year": 2018,
        "chronology": {
            "id": "ISO",
            "calendarType": "iso8601"
        }
},

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.