Git Product home page Git Product logo

java's Introduction

java's People

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  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  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

java's Issues

Component finder results in nullpointer in version 0.6

For a quick test i just wanted to scan everything on a small pet project. So i did:
new NameSuffixComponentFinderStrategy("")

Unfortunately this results in

java.lang.NullPointerException at com.structurizr.componentfinder.ComponentFinder.foundComponent(ComponentFinder.java:39)

Its ok for me if an empty string does not return anything. It wasn't a valid regex or anything.
But a nullpointer seems less then ideal to me ;-)
But then i looked a little deeper and it seems that the nullpointer is the result of an anonymous inner class. The empty suffix is allowed. It matches everything. But matching the inner class results in an error due because type.getCanonicalName() is null when type is an inner class.

references between containers now being displayed on system diagrams

Hello,

Not sure if this is as intended but I have for example an User that uses a container and I would expect that relationship would show up when displaying system diagram for the system that owns the container and same user. Currently I have to resort to adding that connection at both levels to achieve what I want.

Structurizr plantuml sequence diagram

I just exported a DynamicView from structurizr as plantuml and was surprised that this did not generate a plantuml sequence diagram. I wouldn't directly consider this a bug, but I definitely feel that it would be good if it could.

Was the choice to not export a sequence diagram intentional? I could probably contribute a fix that makes it generate sequence diagrams, but I'd first like to know if this is wanted behavior. Or maybe there should be an option?

Structurizr could not find components in an application using spring boot 2.0.0.M7

I am trying to document an application that uses spring boot version 2.0.0.M7. But The problem am having is that when i use "structurizr-spring" dependency to auto scan components it fails to locate them. I can see from my logs that when the component finder tries to find files that are specified (as packageToScan parameter) it goes through all the files existing in classpath including the jar file for the application.

My project structure looks like this. I have application package and architecture package ( structurizr) gradle projects in the same level and in architecture's build.gradle i have added compile dependency to the application.

  • app

  • architecture

Here is code excerpt that shows how i am trying to find spring components

 ` ComponentFinder componentFinder = new ComponentFinder(
            webApplication, "com.mypackage.name",
            new SpringComponentFinderStrategy(
                    new ReferencedTypesSupportingTypesStrategy()
            )
    );

   componentFinder.findComponents();
 `

IllegalArgumentException: A component type must be provided

Hi.
When running ComponentFinder.componentFinder I get my log littered with warnings, e.g:

2018-10-31 09:17:50.980 [main] WARN  com.structurizr.analysis.AbstractComponentFinderStrategy - java.lang.IllegalArgumentException: A component type must be provided.

As far as I've debugged, the exception comes from here https://github.com/structurizr/java/blob/master/structurizr-core/src/com/structurizr/model/Container.java#L163
and is logged here
https://github.com/structurizr/java/blob/master/structurizr-analysis/src/com/structurizr/analysis/AbstractComponentFinderStrategy.java#L135

The problem are all the calls to Container.getComponentOfType using Class.getCanonicalName() as argument, since the latter can return null in a number of cases, like anonymous and local classes. For instance, for class ch.qos.logback.core.subst.Tokenizer$1.

So, you should null check getCanonicalName() and ignore those classes or perhaps use the !isNestedClass(type) check, which is used in another place in the file.

Documentation tests fail

I cloned the repo yesterday and the Documentation tests all fail with:
java.lang.AssertionError
at org.junit.Assert.fail(Assert.java:86)
at org.junit.Assert.assertTrue(Assert.java:41)
at org.junit.Assert.assertTrue(Assert.java:52)
at com.structurizr.documentation.DocumentationTests.test_addImage_ThrowsAnException_WhenTheSpecifiedFileDoesNotExist(DocumentationTests.java:335)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:26)
at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:117)
at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:42)
at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:253)
at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:84)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)

However if I change the test from:

@Test
    public void test_addImage_ThrowsAnException_WhenTheSpecifiedFileIsNotAFile() throws IOException {
        try {
            documentation.addImage(new File(".//test/unit/com/structurizr/documentation/"));
        } catch (IllegalArgumentException iae) {
            assertTrue(iae.getMessage().endsWith("/structurizr-core/test/unit/com/structurizr/documentation is not a file."));
        }
    }

to :

    @Test(expected = IllegalArgumentException.class)
    public void test_addImage_ThrowsAnException_WhenTheSpecifiedFileIsNotAFile() throws IOException {
            documentation.addImage(new File(".//test/unit/com/structurizr/documentation/"));
    }

It runs fine, is there a reason not to use the @Test(expected = IllegalArgumentException.class) construct? If not I will make a pull request for it.

Add a SpringWebserviceEndpointFinderStrategy

I wondering whether or not it would be interesting to add a SpringWebserviceEndpointFinderStrategy, which will look for org.springframework.ws.server.endpoint.annotation.Endpoint annotations.
This would require org.springframework.ws:spring-ws-core:2.4.2.RELEASE to be added as a dependency.

For now I implemented that SpringWebserviceEndpointFinderStrategy as a util in my project, but I willing to contribute it back.
Or is using the AnnotationTypeMatcher the recommended approach?

SourceCodeComponentFinderStrategy: make file encoding configurable

It appears to my that SourceCodeComponentFinderStrategy only supports UTF-8 as file encoding.
As a default that's the right thing to do.
But it would be nice to be able to specify the encoding, for example we have a case where "iso-8859-1" is used in the project.
In the implementation of #runJavaDoc in SourceCodeComponentFinderStrategy, you could pass the configured file encoding via the "-encoding" command line parameter to the doclet.

No common interface to create element relationships

It is not possible to write code that creates relationships for elements of different types because the abstract class StaticStructureElement is not public. The alternative to make StaticStructureElement public would be an interface that contains the public "uses" methods.
There is also no uses method with a more common destination argument, for example of type StaticStructureElement...

Allow subclassing PlantUMLWriter

PlantUMLWriter currently has a lot of private methods. Please consider making them protected instead, to allow tweaking the behaviour of the PlantUML export without having to duplicate the entire class.

Java.lang.classnotfound exception when running GettingStarted.java example

Hi,
I am new to structurizr and I am unable to resolve the following issue:
Code
structurizrClient.putWorkspace(WORKSPACE_ID, workspace);
Error Message
Apr 17, 2018 11:04:07 AM com.structurizr.api.StructurizrClient putWorkspace
INFO: Putting workspace with ID 38873
Exception in thread "main" java.lang.NoClassDefFoundError: com/structurizr/io/json/JsonWriter
at com.structurizr.api.StructurizrClient.putWorkspace(StructurizrClient.java:188)
at com.structurizr.example.GettingStarted.main(GettingStarted.java:50)
Caused by: java.lang.ClassNotFoundException: com.structurizr.io.json.JsonWriter
at java.net.URLClassLoader.findClass(Unknown Source)
at java.lang.ClassLoader.loadClass(Unknown Source)
at sun.misc.Launcher$AppClassLoader.loadClass(Unknown Source)
at java.lang.ClassLoader.loadClass(Unknown Source)
... 2 more

I downloaded the file and followed all the steps. But, some files still seem to be missing.

Element.equals() is overridden but Element.hashCode() is not

Shouldn't the results of hashCode() be consistent with the notion of value equality as implemented by .equals()?

Disclaimer: I don't really consider myself a Java programmer. I'm analysing the Java code in the process of producing a Python port of Structurizr.

AbstractReflectionsComponentFinderStrategy only allows for dependencies in the scanned package

I added some components from 3rd party libraries that are used by a lot of spring controllers, and then i scan for the spring controllers. I expected the controllers to be linked the controller but while they all show up in the diagram there is no usage in between. Looking at the code of AbstractReflectionComponentFinderStrategy it seems it only will link components that reside in the scanned package. It would really be useful to allow it to add dependencies to all the already registered components. Or at least make it configurable.
so this if in the addEfferentDependencies is causing this behavior:

` if (referencedTypeName.startsWith(componentFinder.getPackageToScan())) {

                Component destinationComponent = componentFinder.getContainer().getComponentOfType(referencedTypeName);
                if (destinationComponent != null) {
                    if (component != destinationComponent) {
                        component.uses(destinationComponent, "");
                    }
                } else if (!referencedTypeName.equals(implementationType) && depth < 10) {
                    addEfferentDependencies(component, referencedTypeName, ++depth);
                }
            }`

Deployment View does not show component relationships

Greetings! I have a problem with defining component relationships. They are not shown in Deployment view.

Here is examplery code:

package test;

import com.structurizr.Workspace;
import com.structurizr.api.StructurizrClient;
import com.structurizr.model.Container;
import com.structurizr.model.DeploymentNode;
import com.structurizr.model.Model;
import com.structurizr.model.SoftwareSystem;
import com.structurizr.view.ContainerView;
import com.structurizr.view.DeploymentView;
import com.structurizr.view.ViewSet;

public class test {

	private static final long WORKSPACE_ID = 2;
    private static final String API_KEY = "8d30fcd5-1044-46f2-b9e4-e4c8b9881459";
    private static final String API_SECRET = "29e6f7a1-f26e-4197-9bb3-9237e6a6cf01";
    public static void main(String[] args) throws Exception {
    	Workspace workspace = new Workspace("test", "test");
    	Model model = workspace.getModel();
    	SoftwareSystem test = model.addSoftwareSystem("test", "test");
    	Container lb = test.addContainer("lb.domain.com", "Load-Balanser", "NGINX");
    	DeploymentNode lb_node = model.addDeploymentNode("lb.domain.com", "Load-Balanser", "Linux", 1);
    	lb_node.add(lb);
    	Container app = test.addContainer("app.domain.com", "App Server", "WebLogic");
    	DeploymentNode app_node = model.addDeploymentNode("app.domain.com", "App server", "Linux", 1);
    	app_node.add(app);
    	lb.uses(app, "Balancing load");
    
    	ViewSet views = workspace.getViews();
    	ContainerView containerView = views.createContainerView(test, "ContainerView", "test");
        containerView.addAllContainers();
        
        DeploymentView deploymentView = views.createDeploymentView(test, "DeploymentView", "test");
        deploymentView.addAllDeploymentNodes();
        
        StructurizrClient structurizrClient = new StructurizrClient("http://localhost:8880/api", API_KEY, API_SECRET);
        structurizrClient.putWorkspace(WORKSPACE_ID, workspace);
    }
	
}

Resulting Component View:
cv
Resulting Deployment View:
dv
What is going wrong?

Running into issues with SpringComponentFinderStrategy tripping over multiple interface hits

Working with this strategy:

        new ComponentFinder(
            attackPath, "com.example.svc",
            new SpringComponentFinderStrategy(
                new ReferencedTypesSupportingTypesStrategy()
            ),
            new SourceCodeComponentFinderStrategy(
                sourceRoots.get("example-svc").toFile(),
                150
            )
        ).findComponents();

As it is running through the classes, it comes across one that looks like this:

@Component
public class SomethingUpdateDbConsumer implements Consumer<List<Some>> {

The AbstractSpringComponentFinderStrategy.findInterfacesForImplementationClassesWithAnnotation() method sees the interface java.util.function.Consumer and decides that this component should be represented as that.

However, a few loop iterations later, it finds this guy:

@Component
public class OtherthingUpdateDbConsumer implements Consumer<List<Other>> {

And going through the same logic as before, tries to add a second component named Consumer which blows up.

At the top of the loop, there is a check for whether the candidate component already exists in the components, but it is checking on the simple name, not the interface name, so it doesn't see a problem, and there isn't a check whether this interface name already exists prior to trying to insert it.

So.. a few questions:

  1. I don't really want these guys to be represented by something as abstract and unrelated to my architecture as java.lang.function.Consumer. However, I haven't yet found a nice way to be able to blacklist the interface or tell the strategy to stop looking at interfaces at all. What to do?
  2. In the case of my actual classes like *RepositoryImpl, they aren't getting de-interfaced because the interface they implement is something called *RepositoryExtras which extends from an interface called *Repository which extends from org.springframework.data.repository.CrudRepository. Bleh. It doesn't look like this AbstractSpringComponentFinderStrategy tries to do any recursive interpretation of interfaces, should I just write off trying to use the SpringComponentFinderStrategy entirely because my code base is too "fancy" for it?

How to create a Structurizr model for multiple Spring Applications in different maven modules?

Situation:

  • app1 (maven module Spring Application)
  • app2 (maven module Spring Application)

How to describe this situation in one Structurizr model?

I tried creating a module documentation and adding dependencies on app1 and app2, but since these are Spring Boot Applications, they are bundled into a single jar and component finding fails.

Other option could be finding components in each application individually and then putting them together somehow.

How would you solve this?

BTW ( #44 might be related)

After I have saved a model on structurizr and reading it with the client again, I get a Nullpointer Exception

I had an existing model (workspace 111), saved it on structurizr and then fetched it again with the client. Then I got the following exception:

Exception in thread "main" com.structurizr.io.StructurizrReaderException: Could not read JSON
at com.structurizr.io.json.JsonReader.read(JsonReader.java:23)
at com.structurizr.api.StructurizrClient.getWorkspace(StructurizrClient.java:104)
at com.structurizr.api.StructurizrClient.mergeWorkspace(StructurizrClient.java:152)
at at.gv.justiz.ju30.architecture.Target2015.main(Target2015.java:143)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:483)
at com.intellij.rt.execution.application.AppMain.main(AppMain.java:134)
Caused by: com.fasterxml.jackson.databind.JsonMappingException: (was java.lang.NullPointerException) (through reference chain: com.structurizr.Workspace["model"]->com.structurizr.model.Model["softwareSystems"]->com.structurizr.model.SoftwareSystem["relationships"])
at com.fasterxml.jackson.databind.JsonMappingException.wrapWithPath(JsonMappingException.java:232)

Using structurizr for c code?

Hi,

Apologies if this is an uninformed question. I understand that you need to use java to construct a code model that structurizr can consume. However, is it possible to analyze code that is written in a different language, such as C or C++?

New Release (or Release Candidate)

Feels to me like there's been significant progress & changes since September and so perhaps it's time for another release candidate or final release.

Is there any reason not to cut an RC5 release soon? (eta??)

If a full release is preferred then are there any blocking issues holding that up that I could help unblock?

MD5 hash doesn't match content

After upgrading to structurizr 0.3.0, I'm getting the following debug message on structurizrClient.mergeWorkspace:

Mai 11, 2015 10:03:21 PM com.structurizr.api.StructurizrClient debugResponse
INFORMATION: HTTP/1.1 401 Unauthorized
Mai 11, 2015 10:03:21 PM com.structurizr.api.StructurizrClient putWorkspace
INFORMATION: {"message":"MD5 hash doesn't match content"}

API-Token is correct for sure, I'm using workspace ID 111

Diagram writer interface to be able to produce multiple files

In case of PlantUML, the processor to image expects to receive one diagram at a time.

Current interface of writers doesn't allow returning multiple diagrams separately. I had to split the string on "@startuml" line and save as individual files.

SpringComponentFinderStrategy

Hi guys,

I'm like using Structurizr to create my architecture documentation.
But i have recently ran into a class not found exception:

Container apiBackend = company.addContainer("Backend API", "Provides and Receives company data via JSON/HTTPS API.", "js");

ComponentFinder serviceFinder = new ComponentFinder(apiMiddleware, "com.company.services", new SpringComponentFinderStrategy(
                new ReferencedTypesSupportingTypesStrategy(false)
        ));

This package only contains @service annotations.

But when i run this i get:

Exception in thread "restartedMain" java.lang.reflect.InvocationTargetException
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.lang.reflect.Method.invoke(Method.java:497)
	at org.springframework.boot.devtools.restart.RestartLauncher.run(RestartLauncher.java:49)
Caused by: java.lang.NoClassDefFoundError: org/springframework/data/jpa/repository/JpaRepository
	at com.structurizr.analysis.SpringRepositoryComponentFinderStrategy.findSpringRepositoryInterfaces(SpringRepositoryComponentFinderStrategy.java:41)
	at com.structurizr.analysis.SpringRepositoryComponentFinderStrategy.doFindComponents(SpringRepositoryComponentFinderStrategy.java:28)
	at com.structurizr.analysis.AbstractComponentFinderStrategy.findComponents(AbstractComponentFinderStrategy.java:57)
	at com.structurizr.analysis.SpringComponentFinderStrategy.doFindComponents(SpringComponentFinderStrategy.java:61)
	at com.structurizr.analysis.AbstractComponentFinderStrategy.findComponents(AbstractComponentFinderStrategy.java:57)
	at com.structurizr.analysis.ComponentFinder.findComponents(ComponentFinder.java:74)
	at com.neanex.MiddlewareApplication.main(MiddlewareApplication.java:79)
	... 5 more
Caused by: java.lang.ClassNotFoundException: org.springframework.data.jpa.repository.JpaRepository
	at java.net.URLClassLoader.findClass(URLClassLoader.java:381)
	at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
	at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:331)
	at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
	... 12 more```

Can you guys point me in the right direction?
Extra info: I'm only using 1 CrudRepository for redis and it's not situated in that package, but in a repositories package.

kind regards

ComponentFinder - Support for multiple packages to scan (multi-module builds)

Hi

Field/parameter "packageToScan" is now a String value, limiting packages to scan to one single package. As I do not want to scan the entire codebase, it would be convenient to be able to list multiple sub-packages to scan.

It seems like a quick fix in AbstractReflectionsComponentFinderStrategy

.filterInputsBy(new FilterBuilder().includePackage(componentFinder.getPackageToScan()))

the includePackage method in the reflections API takes a vararg of Strings, making it possible to easily refactor ComponentFinder to accept a list/array of packages to scan.

essentially changing this line to

.filterInputsBy(new FilterBuilder().includePackage(componentFinder.getPackagesToScan()))

that is, changing getPackageToScan to getPackagesToScan

This is also very relevant for multi-module builds.
E.g. when controllers depend upon services/repositories from other maven-modules.

PlantUMLWriter writes complete workspace

By default the PlantUMLWriter writes the complete workspace into one single puml file.
When using puml file in asciidoctor, a single UML diagram is expected per file. Starting with @startuml en ending with @enduml.

To be able to write a single View, expose all write(? extends View view, Writer writer) methods.

Publication of the structurizr-dot artifact in a maven repository

As far as i can tell, i can't find the "structurizr-dot" jar artifact published anywhere [*], could it be possible to activate the publication of this submodule for the next release ?
(i've seen that there are really not a lot of code in the module, but it would be cleaner to just re-use it)

[* : not found here http://jcenter.bintray.com/com/structurizr/ for example ]

Generated json files cluttering workspace

Each time I create a diagram it is generating this json file, which is fine - however it is generating it in the base directory of my project. It should really be generated in the base directory of the module.

i.e. not in /ore but inside /diagrams

Right now I have to append the projects .gitignore to stop these being committed but this means the project then knows about structurizer, I would much rather have edit the specific .gitignore inside of /diagrams and keep everything to do with structurizer inside here.

output

Exception NoClassDefFoundError for SourceCodeComponentFinderStrategy

Hi
I am trying to use a ComponentFinder based on a SourceCodeComponentFinderStrategy:
ComponentFinder componentFinder = new ComponentFinder( forceCFI, "instru", new SourceCodeComponentFinderStrategy(new File(sourceRoot, "/src/"), 150)); componentFinder.findComponents();

but I get the following exception:
Exception in thread "main" java.lang.NoClassDefFoundError: com/sun/tools/javadoc/Main at com.structurizr.analysis.SourceCodeComponentFinderStrategy.runJavaDoc(SourceCodeComponentFinderStrategy.java:118) at com.structurizr.analysis.SourceCodeComponentFinderStrategy.afterFindComponents(SourceCodeComponentFinderStrategy.java:62) at com.structurizr.analysis.ComponentFinder.findComponents(ComponentFinder.java:76) at Test.main(Test.java:102) Caused by: java.lang.ClassNotFoundException: com.sun.tools.javadoc.Main at java.net.URLClassLoader.findClass(URLClassLoader.java:381) at java.lang.ClassLoader.loadClass(ClassLoader.java:424) at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:335) at java.lang.ClassLoader.loadClass(ClassLoader.java:357) ... 4 more

I tried to google search about the fail of the loading of the class but did not find anything usefull. I tried also to replace the OpenJDK by the Sun JDK but the error is still there. Is this a bug or I missed something ?

Spring Pet Clinic demo doesn't have public controllers

I was following tutorial at https://github.com/structurizr/java/blob/master/docs/spring-petclinic.md, but I was still getting component view without controllers, until I found that SpringComponentFinderStrategy by default ignores non-public classes.

Since spring-projects/spring-petclinic@83ff9a5 controllers in pet clinic are not public which causes trouble following the tutorial for Pet Clinic.

Maybe referencing fixed revision in the tutorial could help.

How can you avoid two ComponentFinderStrategies both finding the same component?

I'm catching a bunch of components using the SpringAnnotations, but there are a few stragglers that I'm trying to catch using a RegexTypeMatcher.

I've run into a problem where one class that I'm trying to capture with the RegexTypeMatcher is also annotated with a Spring @component which causes the componentFinder to throw an IllegalArgumentException: A component named 'xxx' already exists for this container.

The scanning application continues on with the other scans, but it doesn't upload at the end. I was naively expecting that it would consolidate components found with more than one strategy within the same component. Do I have to manually try to avoid such a circumstance or am I maybe missing something?

Can't import "com.structurizr.api.StructurizrClient"

Hello,

I am trying to use Structurizr with Maven, but unfortunately I can't import the "com.structurizr.api.StructurizrClient" class (version 0.6.0) even if I am following the tutorial you provided.

I ran the "./gradlew publishToMavenLocal" command and I added the dependencies to my pom file. Everything loads and works fine until I try to import the "com.structurizr.api.StructurizrClient" class. In fact in my dependencies (even if I have them in my pom file), I can't see any jar called "structuriz-client-0.6.0.jar".

I checked in my local Maven repository and I couldn't find the jar there. I can't manually download the jar file from Bintray, so I tried to find another solution to my problem.

Currently I made it work by downloading version 0.3.2 of Structurizr and then by manually adding to the build path of my project "structuriz-client-0.3.2.jar". This allows me to import (and use) the "com.structurizr.api.StructurizrClient" class.

It looks like that in the Bintray repository the client-0.6.0 jar file is not there, or am I doing anything wrong?

Thanks!

Web interface ignores Papersize

I have trouble using the method sePaperSize(). When reloading the Structurizr workspace, the paper_size seems to ignore the java calls I made:

    ` SystemContextView contextView = views.createSystemContextView(irma, "Overview", "Kharon architecture");
    contextView.addAllSoftwareSystems();
    contextView.add(user);
    contextView.setPaperSize(PaperSize.A5_Landscape);

    // Software view
    SystemContextView contextView = views.createSystemContextView(irma, "Overview", "Kharon architecture");
    contextView.addAllSoftwareSystems();
    contextView.add(user);
    contextView.setPaperSize(PaperSize.A5_Landscape);

    // Who view
    SystemContextView whoView = views.createSystemContextView(irma, "Who", "Kharon architecture");
    whoView.addAllSoftwareSystems();
    whoView.addAllPeople();
    whoView.setPaperSize(PaperSize.A5_Landscape);`

and I always get an A4 Portrait on the website, except for the 1st diagram (SystemContext) that seems to take the call into account the A5 landscape call...

IllegalArgumentException in AdrToolsImporter while parsing DecisionStatus

We have an application, which generates the diagrams, populates the documentation and parses the ADRs. When I run locally everything works fine, but when it runs on our build-server or at a co-workers computer. the application fails due to a IllegalArgumentException.

Caused by: java.lang.IllegalArgumentException: No enum constant com.structurizr.documentation.DecisionStatus.
 	at java.lang.Enum.valueOf(Enum.java:238)
 	at com.structurizr.documentation.DecisionStatus.valueOf(DecisionStatus.java:6)
 	at com.structurizr.documentation.AdrToolsImporter.extractStatus(AdrToolsImporter.java:142)
        at com.structurizr.documentation.AdrToolsImporter.importArchitectureDecisionRecords(AdrToolsImporte/.java:83)

Based upon the stacktrace I concluded that actual name of the DecisionStatus does not get returned from the statusRegex matcher.group(1). I assume it return an emptyString.

The most apparent difference is that I use a Mac and the build-server and my co-worker run Windows as the OS. I will try to troubleshoot this some further.

Using: Structurizr 1.0.0-RC7

Person with Internal Location appearing as External in a Container View

I have the following code which generate a context and container view. Unfortunaly the objects distributor and admin type Person doesn't appear inside the enterprise context of a container diagram but in a context diagram it does.

See my code snippet:

Workspace workspace = new Workspace("MyPlatform", "My online platform");
Model model = workspace.getModel();
Person distributor = model.addPerson(Location.Internal,"Distributor", "A distributor");
Person admin = model.addPerson(Location.Internal,"Admin", "An Admin");
SoftwareSystem platform = model.addSoftwareSystem(Location.Internal, "My Platform", "A platform.");
administrator.uses(platform, "Manage all accounts");
...
Container distributorApplication = platform.addContainer("Distrib. App", "A distributor mobile app" "Android");
distributor.uses(distributorApplication, "Uses", "JSON/HTTPS");
Container adminApplication = platform.addContainer("Admin App", "An admin web app", "React");
admin.uses(adminApplication, "Block an account", "JSON/HTTPS");
...

ViewSet views = workspace.getViews();
SystemContextView contextView = views.createSystemContextView(platform, "SystemContext", "A context diagram");
contextView.setPaperSize(A5_Landscape);
contextView.addAllSoftwareSystems();
contextView.addAllPeople();

ContainerView containerView = views.createContainerView(platform, "Container", "A container diagram");
containerView.setPaperSize(A4_Landscape);
containerView.addAllElements();
containerView.addAllSoftwareSystems();
containerView.addAllPeople();

...

Any idea how to solve this?

ComponentFinder crashes on inner classes

All the SupportingTypesStrategy implementations in structurizr-core seem to use Class::getCanonicalName to convert Class objects to Strings. Later these strings are converted back to classes via ClassLoader::loadClass in TypeUtils.getVisibility. Unfortunately this does not work for inner classes.
For the class Inner in class Bar in package foo e.g.

Class::getCanonicalName = foo.Bar.Inner
Class::getName = foo.Bar$Inner

and in ClassLoader::loadClass you must use foo.Bar$Inner to load the inner class. foo.Bar.Inner will lead to an exception like the one I see when running ComponentFinder on my project:

Exception in thread "main" java.lang.IllegalArgumentException: The specified type could not be found.
	at com.structurizr.analysis.TypeUtils.getVisibility(TypeUtils.java:33)
	at com.structurizr.analysis.AbstractComponentFinderStrategy.findSupportingTypes(AbstractComponentFinderStrategy.java:85)
	at com.structurizr.analysis.AbstractComponentFinderStrategy.afterFindComponents(AbstractComponentFinderStrategy.java:70)
	at com.structurizr.analysis.ComponentFinder.findComponents(ComponentFinder.java:76)

SourceCodeComponentFinderStrategy fails to extract any description!

We have a potentially weird setup (although surely not that uncommon):

Our source repo contains com.example.ThingImpl which implements a com.example.Thing interface which we inherit from an dependency jar (it's generated from a swagger definition through ci). We religiously add relevant javadocs to the implementation but the generated interface has none.

Running some of the spring component finders manages to identify a component "Thing" with CodeElements for Thing (interface, primary) and ThingImpl (class, supporting). Then when trying to identify the Component description it considers the non-existent interface description but ignores ThingImpl's juicy javadocs because it's a "supporting" class.

Proposal: Modify SourceCodeComponentFinderStrategy so that:

  1. If the Component already has a description then don't touch it.
  2. Else prefer any Primary CodeElement description.
  3. Else accept any Supporting CodeElement description.
  4. Else give up and leave a blank description.

I'm slightly concerned about what might happen if multiple documented Primary CodeElements are found with javadocs - which will be picked? Similarly with multiple documented Secondary CodeElements are found. But I know this isn't the case for my code base so I'm ignoring it for now.

Any improvements to this approach?

Unauthorized

Hi Simon,

I'm trying to updat a Structurizr workspace but failing for some reason. Just today was able to update.
WorkspaceID = 20371
I believe both key and secret are correct...

Exception I get:
Structurizr.Client.StructurizrClientException was unhandled
HResult=-2146233088
Message=There was an error putting the workspace: The remote server returned an error: (401) Unauthorized.
Source=Structurizr.Core
StackTrace:
at Structurizr.Client.StructurizrClient.PutWorkspace(Int64 workspaceId, Workspace workspace)
at ConsoleApplication1.Program.Main(String[] args) in C:\Users\XXX\documents\visual studio 2015\Projects\ConsoleApplication1\ConsoleApplication1\Program.cs:line 64
at System.AppDomain._nExecuteAssembly(RuntimeAssembly assembly, String[] args)
at System.AppDomain.ExecuteAssembly(String assemblyFile, Evidence assemblySecurity, String[] args)
at Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly()
at System.Threading.ThreadHelper.ThreadStart_Context(Object state)
at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
at System.Threading.ThreadHelper.ThreadStart()
InnerException:
HResult=-2146233079
Message=The remote server returned an error: (401) Unauthorized.
Source=System
StackTrace:
at System.Net.WebClient.UploadDataInternal(Uri address, String method, Byte[] data, WebRequest& request)
at System.Net.WebClient.UploadString(Uri address, String method, String data)
at System.Net.WebClient.UploadString(String address, String method, String data)
at Structurizr.Client.StructurizrClient.PutWorkspace(Int64 workspaceId, Workspace workspace)
InnerException:

Json Schema - Implementation Validation

I would like to have a json schema to be generated from the current code to allow other implementations (.NET, ruby, php, etc.) to be able to keep up-to-date with the latest object model of the REST api for the Structurizr site.

I will issue a pull request for this issue with my first cut of this.

Thanks.

DotWriter/GraphViz too limited to visualize workspace?

I decided to take a stab at C4 and work out a workspace. I was already using GraphViz and Dot for automatically generated graph visualizations and was hoping that a C4 workspace can visualized using Dot/GraphViz. I find that the DotWriter spits out dot content just fine, but that GraphViz cannot create a complete image for a more complex workspace... Is that your experience as well?
I was hoping for GraphViz to visualize all the defined views in the workspace in one image, but only the first digraph ends up in the image. Online GraphViz versions confirm the behavior.

Working with the .NET framework, I ported your Java DotWriter to C# (easy) and did a crude port of Java LivingDocumentation.DotDiagram to C# (harder). Then I used one of your example workspaces, Big Bank plc, to try out the ported DotWriter/DotDiagram and found that the dot content contains several digraphs, but GraphViz only visualizes the first one...

add(Relationship relationship) in DynamicView doesn't work correct

The method add(Relationship relationship) in DynamicView doesn't work as expected. The relationships don't get a sequence number. And the second attempt to upload the diagram results in an exception. If I use add(Element source, String description, Element destination) with the information from my relationship object instead all works well...

Model allows multiple Components to exist within a Container

Component extends Element and therefore has a hashCode() based purely on Element.name. Container has a LinkedHashSet of Component and therefore is limited to one Component of any given name. So it seems safe to assume that a Container is designed to only contain one Component of any given name.

Model.addComponent(..) methods (unlike addPerson(..), addSoftwareSystem(..), addContainer(..)) fails to check the component is new before adding it, thereby overrides the first Component of that name with a second. When using SequentialIntegerIdGeneratorStrategy both first and second instances get different ids and so both end up in the Model.elementsById index (which is weird). When using MessageDigestIdGenerator then the both get the same id, the first ends up in the index but the second ends up in the Container (which is probelmatic).

A real world example of this can be found using the ComponentFinder to find a component that happens to both implement CrudRepository AND be annotated @Repository.

Suggest that Model.addComponent(..) methods are modified to block addition of duplicates in the first place, like their sibling add methods, and that callers are modified to avoid adding duplicates. Will put together a PR along these lines unless I hear objections.

Multhreading isuue

Hello,
I really like your topics and the way you explain. I am a computer science student. I am developing an desktop app that would help farmers get to know the best seed for the area based on the database of experts. I did that well but I also wanted them to be updated on what to do every time there has to be an activity on their crops for instance weed, apply fertilizer etc. I have a table of timing which stores duration for a given crop and what my program does it subtract the starting date as the planting date from the current date and checks from the timing table if the differences in dates matches the duration stored for the crop it fetches the action. I have tried doing a thread but it is not fetching the action. Kindly this is the section of the code.
String selcted_crop = crop();
String selcted_place = activity_Area();

try {
    String s = "Insert into activities(id_Number, f_Name, l_Name, phone_Number, start_Date, crop_ID, place_ID, farm_Size)values(?,?,?,?,?,?,?,?) ";
    pst = conn.prepareStatement(s);
    pst.setString(1, id_Number.getText());
    pst.setString(2, f_Name.getText());
    pst.setString(3, s_Name.getText());
    pst.setString(4, phone_Number.getText());
    pst.setString(5, ((JTextField) jDateChooser2.getDateEditor().getUiComponent()).getText());
    pst.setString(6, selcted_crop);
    pst.setString(7, selcted_place);
    pst.setString(8, farm_Size.getText());
    pst.executeUpdate();
    JOptionPane.showMessageDialog(null, "Record Saved");

    String plc1[] = new String[100];
    String placeve = "";

    Thread t = new Thread() {
        public void run() {
            for (;;) {
                Calendar c = new GregorianCalendar();
                int year = c.get(Calendar.YEAR);
                int month = c.get(Calendar.MONTH);
                int day = c.get(Calendar.DAY_OF_MONTH);

                int hour = c.get(Calendar.HOUR);
                int min = c.get((Calendar.MINUTE));
                int sec = c.get(Calendar.SECOND);

                CurrentDate = year + "-0" + month + day;
                CurrentHour = "0" + hour + min + sec;

            }
        }
    };
    t.start();

    for (int i = 0; i <= 3; i++) {
        try {
            String stl = "Select *from vendors where place_ID = '" + place_ComboBox.getSelectedItem().toString() + "'";
            pst = conn.prepareStatement(stl);
            rst = pst.executeQuery();
            while (rst.next()) {
                plc1[i] = rst.getString("vendor_Name");
                JOptionPane.showMessageDialog(null, plc1[i]);

            }
        } catch (Exception e) {

        }
    }

    String name = f_Name.getText();
    try {
        String g = "select *from activity where s_name=?";
        pst = conn.prepareStatement(g);
        pst.setString(1, name);
        rst = pst.executeQuery();
        if (rst.next()) {
            name = rst.getString("s_Name");
        }
    } catch (Exception e) {

    }
    String crop1 = crop_ComboBox.getSelectedItem().toString();
    String crop_ID = "";
    try {
        String l = "select *from crops where crop_Name=?";
        pst = conn.prepareStatement(l);
        pst.setString(1, crop1);
        rst = pst.executeQuery();
        if (rst.next()) {
            crop_ID = rst.getString("crop_ID");
        }
    } catch (Exception e) {
        JOptionPane.showMessageDialog(null, e);
    }
    String plc = place_ComboBox.getSelectedItem().toString();
    String place_ID = "";
    try {
        String re = "select *from places where place_Name=?";
        pst = conn.prepareStatement(re);
        pst.setString(1, plc);
        rst = pst.executeQuery();
        if (rst.next()) {
            place_ID = rst.getString("place_ID");
        }
    } catch (Exception e) {
        JOptionPane.showMessageDialog(null, e);
    }

    String pie = "";
    String pie1 = "";
    try {
        String b = "select * from seeds where crop_ID=? and place_ID=?";
        pst = conn.prepareStatement(b);
        pst.setString(1, crop_ID);
        pst.setString(2, place_ID);
        rst = pst.executeQuery();

        if (rst.next()) {
            pie = rst.getString("seed_Name");
            pie1 = rst.getString("seed_ID");
            JOptionPane.showMessageDialog(null, "Hujambo " + name + ", You are being informed that the best seed for you is " + pie + ". KIndly buy the seeds from a trusted vendor");
        }
    } catch (Exception e) {
        JOptionPane.showMessageDialog(null, e);
    }

    int uniqueid = 0;
    String action = "";
    String cp[] = new String[1000];
    int diffDays[] = new int[100];
    String pNumber = phone_Number.getText();
    for (int i = 0; i < uniqueid; i++) {
        try {
            String str = "Select *from activities where phone_Number = '" + pNumber + "'";
            pst = conn.prepareStatement(str);
            rst = pst.executeQuery();
            while (rst.next()) {
                String dp = rst.getString("start_Date");
                String kp = rst.getString("cropId");
            }

        } catch (Exception e) {

        }
        int dur = 0;

        try {
            String ke = "select from actions where seed_ID='" + pie1 + "'";
            pst = conn.prepareStatement(ke);
            rst = pst.executeQuery();
            while (rst.next()) {
                action = rst.getString("action");
                if (rst.next()) {
                    dur = rst.getInt("Duration");
                    action = rst.getString("action");
                    if (diffDays[i] == dur) {
                        JOptionPane.showMessageDialog(null, "Kindly it has gone'" + dur + "' you are being informed to '" + action + "'");
                    }

                }

            }
        } catch (Exception e) {

        }
    }
} catch (Exception e) {
    JOptionPane.showMessageDialog(null, e);

}

Using maven-exec-plugin alongside with SourceCodeComponentFinderStrategy fails

I have a maven multi-module application (see also #58),

Parts of the system:

  • spring boot application maven module "App module"
  • documentation maven module "documentation"
    • has main class with SpringComponentFinderStrategy and SourceCodeComponentFinderStrategy
    • has maven dependency on the App module (plus structurizr
    • Situations indocumentation module:
      • (A) without any plugins
      • (B) with maven-exec-plugin running main class of "documentation" module as a part of build process.

In situation (A) calling the documentation main manually works well and finds controller from the App module.

In situation (B) let maven build invoke the main, the following error shows up:

java.lang.reflect.InvocationTargetException
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at java.lang.reflect.Method.invoke(Method.java:483)
        at org.codehaus.mojo.exec.ExecJavaMojo$1.run(ExecJavaMojo.java:294)
        at java.lang.Thread.run(Thread.java:745)
Caused by: java.lang.NoClassDefFoundError: com/sun/tools/javadoc/Main
        at com.structurizr.analysis.SourceCodeComponentFinderStrategy.runJavaDoc(SourceCodeComponentFinderStrategy.java:118)
        at com.structurizr.analysis.SourceCodeComponentFinderStrategy.afterFindComponents(SourceCodeComponentFinderStrategy.java:62)
        at com.structurizr.analysis.ComponentFinder.findComponents(ComponentFinder.java:76)

Skipping the SourceCodeComponentFinderStrategy results in "fixing" this errors, but doesn't return any found components.

AesEncryptionStrategyTests is failing when incorrect key size is used

./gradlew test fails:

java.lang.Exception: Unexpected exception, expected<javax.crypto.BadPaddingException> but was<java.security.InvalidKeyException>
    at org.junit.internal.runners.statements.ExpectException.evaluate(ExpectException.java:28)
    at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78)
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57)
    at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
    at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
    at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
    at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
    at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
    at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
    at org.gradle.api.internal.tasks.testing.junit.JUnitTestClassExecuter.runTestClass(JUnitTestClassExecuter.java:86)
    at org.gradle.api.internal.tasks.testing.junit.JUnitTestClassExecuter.execute(JUnitTestClassExecuter.java:49)
    at org.gradle.api.internal.tasks.testing.junit.JUnitTestClassProcessor.processTestClass(JUnitTestClassProcessor.java:69)
    at org.gradle.api.internal.tasks.testing.SuiteTestClassProcessor.processTestClass(SuiteTestClassProcessor.java:48)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:483)
    at org.gradle.messaging.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:35)
    at org.gradle.messaging.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:24)
    at org.gradle.messaging.dispatch.ContextClassLoaderDispatch.dispatch(ContextClassLoaderDispatch.java:32)
    at org.gradle.messaging.dispatch.ProxyDispatchAdapter$DispatchingInvocationHandler.invoke(ProxyDispatchAdapter.java:93)
    at com.sun.proxy.$Proxy2.processTestClass(Unknown Source)
    at org.gradle.api.internal.tasks.testing.worker.TestWorker.processTestClass(TestWorker.java:105)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:483)
    at org.gradle.messaging.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:35)
    at org.gradle.messaging.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:24)
    at org.gradle.messaging.remote.internal.hub.MessageHub$Handler.run(MessageHub.java:355)
    at org.gradle.internal.concurrent.DefaultExecutorFactory$StoppableExecutorImpl$1.run(DefaultExecutorFactory.java:64)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
    at java.lang.Thread.run(Thread.java:745)
Caused by: java.security.InvalidKeyException: Illegal key size

Pluggable IdGenerator

I notice that you've gone to the effort of having an IdGenerator interface as if it were pluggable, but in Model.java the implementation is hard coded to SequentialIdGeneratorStratergy:

private SequentialIntegerIdGeneratorStrategy idGenerator = new SequentialIntegerIdGeneratorStrategy();

Any objection to this becoming truly pluggable so that alternate implementations can be used?

For example, I repeatedly find myself speculating that it would be useful to have a stable IdGenerator such that as code evolves the same components generate the same ids each run. I'm hopeful that this could have value in linking / merging microservice models into bigger system models; or might have practical value in highlighting changes over time (deleted vs added components)

Instances of components

I'm wondering if there is a good way to model components and actors of which there may be replicas or multiple instances?

For example, if I have an Actor who is using a chat program front-end to communicate with another Actor who is using another instance of the front-end, how would I model this exchange? Both front-ends are instances of the same component, and both talk to the same back-end?

This sort of thing is especially useful in dynamic views to show how users interact with each other through the system.

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.