Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support create java function project #51

Closed
wants to merge 3 commits into from

Conversation

jdneo
Copy link
Member

@jdneo jdneo commented Nov 3, 2017

Work Item: #48

Support create java function project. Currently we will use Maven archetype (call mvn cli) to create a Java typed function project. And we'll change it to function cli when the related part in cli is ready.

UI:
create project

Todo:

-------------- Update on Wed Nov 08 2017 09:59:31 GMT+0800 (China Standard Time) --------------

Add code to support add Java function.

  • Using Maven plugin to do this job.
    Confirmed from Maven plugin team, this command has no batch mode, so I send it to terminal and user can fill in the parameter in the terminal
  • Currently, we determine whether the project is Java based or not by finding pom.xml in the selected folder.

@jdneo jdneo force-pushed the cs-create-java-project branch 2 times, most recently from 8478e55 to 1e5197e Compare November 3, 2017 04:11
Copy link
Contributor

@ejizba ejizba left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This doesn't seem useful until we also support Java functions. Just want to make sure you have a plan to 'disable' this feature if Java function support isn't ready in time for our next release? Should be easy, right?

switch (language.label) {
case TemplateLanguage.Java:
const groupIdPlaceHolder: string = localize('azFunc.java.groupIdPlaceholder', 'groupId');
const groupIdPrompt: string = localize('azFunc.java.groupIdPrompt', 'Provide value of "groupId"');
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These should be 'Provide a value for' instead of 'of'. In addition, there's no need to put 'groupId' in quotes

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Okay

const artifactIdprompt: string = localize('azFunc.java.artifactIdPrompt', 'Provide value of "artifactId"');
const artifactId: string = await ui.showInputBox(artifactIdPlaceHolder, artifactIdprompt, false);

const versionPlaceHolder: string = localize('azFunc.java.versionPlaceHolder', '1.0-SNAPSHOT');
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In general, the placeholder should match the prompt, not the default value

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sure

const appNamePrompt: string = localize('azFunc.java.appNamePrompt', 'Provide value of "appName"');
const appName: string = await ui.showInputBox(appNamePlaceHolder, appNamePrompt, false, undefined, `${artifactId}-${Date.now()}`);

// Use maven command currently, will change to function CLI when the function CLI init project command is ready.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I actually prefer this over using the function cli. All of the core logic is still encapsulated in the mvn archetypeArtifact, but now we get these benefits:

  1. A user can create a Java function project without the func cli installed.
  2. We don't have to wait for the func cli to be updated every time we want to change this

(Plus the func cli doesn't report exit codes correctly or display parse-able output - although both of those should be fixed)

Copy link
Member Author

@jdneo jdneo Nov 7, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Currently, the function CLI doesn't support create Java function project yet. Our plan is leverage the Maven archetype here first. And when the function CLI part is ready, we can change the implementation to using CLI. :)

BTW, according to the newest disscussion with CLI team, it is most likely that the java function project creation part in CLI will leveraging Maven plugin also. So I think we can change to CLI in the future. Anyway we can discuss wether to introduce CLI here in the future :)

await fsUtil.writeFormattedJson(tasksJsonPath, TemplateFiles.tasksJson);
await fsUtil.writeFormattedJson(launchJsonPath, TemplateFiles.launchJson);
const vsCodePath: string = path.join(functionAppPath, '.vscode');
if (!await fse.pathExists(vsCodePath)) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fse.ensureDir does the same as these two commands

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍

await new Promise((resolve: () => void, reject: (e: Error) => void): void => {
const options: cp.SpawnOptions = {
cwd: workingDirectory,
shell: true
};
const childProc: cp.ChildProcess = cp.spawn('func', args, options);
const command: string = languageName === TemplateLanguage.Java ? 'mvn' : 'func';
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

executeCommand could be used for things other than creating a project. Let's pass in 'command' instead of 'languageName'

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Right.


let javaTargetPath: string = '';
switch (language.label) {
case TemplateLanguage.Java:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: Can we move the Java-specific logic into a separate function? I would find it more readable

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Okay.

presentation: {
reveal: 'always'
},
problemMatcher: [
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A lot of this code is copied. Can we encapsulate it? At least the problemMatcher

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sure.

taskName: 'Launch Function App',
identifier: 'launchFunctionApp',
linux: {
command: 'sh -c "mvn clean package && func host start --script-root %path%"'
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Create a separate 'cleanFunctionApp' task and use 'dependsOn' in this task. That way you don't have to define separate 'linux', 'osx', and 'windows' commands

Is 'mvn clean package' necessary before every F5? If so, this might not work since it's a background task (When the user detaches the debugger, func host start is still running in the background...it doesn not get executed again the next time the user F5's)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes mvn clean package is necessary before every F5.

After trying locally, it's exactly as what you said. the preLaunchTask doesn't get executed again. I'm trying to figure out if there is any work around on this. Do you have any suggestions on this?
Currently the user can only hit ctrl+c to manually terminate the function host and hit F5 again.

return JSON.stringify(data, null, ' ');
}

export function getTasksJson(language: string, args: string): string {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would prefer if getTasksJson and getLaunchJson both returned the same type of string (formatted vs unformatted). Doing a stringifyJSON and replace seems inefficient, so I would lean towards returning unformatted strings. (Just modify the object directly - something like taskJsonForJava.tasks[0].command = "func host start --script-root" + scriptRoot)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just modify the object is good for me.

So shall we define the structure of the task json object here? Otherwise the object field cannot be accessed by .. Or we use [] to access the field, but this may raise tslint error.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Whatever works for you - I care more about making the output consistent than how you fix it

In addition, don't feel like you have to follow every tslint rule. This might be a case where you just ignore the rule
screen shot 2017-11-06 at 7 59 53 pm

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the suggestion.


const folder: vscode.WorkspaceFolder | undefined = vscode.workspace.workspaceFolders.find((f: vscode.WorkspaceFolder): boolean => {
return fsPath.startsWith(f.uri.fsPath);
return path.relative(fsPath, f.uri.fsPath) === '';
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm - this definitely fixes some edge cases, but it's not quite what I originally intended the behavior to be. This function should return true even if the path is a subfolder of a workspace. Maybe something like this would work?:

const relativePath: string = path.relative(fsPath, f.uri.fsPath);
return relativePath === '' || !relativePath.startsWith('..');

This logic can be tricky with lots of edge cases, so I'd prefer to add some unit tests when we fix this. You can do that in this PR or file an issue to fix this separately (I don't mind fixing this myself)

Copy link
Member Author

@jdneo jdneo Nov 7, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

My concern is if the subfolder is not opened, the user might not able to launch it since the cwd might not have .vscode folder which contains launch.json and task.json.

Another concern is that as what we discussed above. The maven archetype will always create a artifactId folder first, and put function things into the folder. For Java, there is another important file: pom.xml, will also be put into the artifactId folder. The maven command can be execute only if the cwd contains pom.xml or specify its location in parameter. That's why we prefer to open the folder which contains pom.xml (that is the artifactId folder).

I quite agree that always open the project base path might not be the best solution for this. While I think dong this it not that harmful. What about keeping this change for now and file a issue and we can do more further discussion in detail?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah filing an issue is fine

Copy link
Member Author

@jdneo jdneo Nov 7, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great

@jdneo jdneo force-pushed the cs-create-java-project branch 4 times, most recently from a7cbe1b to cc8d3b7 Compare November 8, 2017 02:11
@jdneo jdneo force-pushed the cs-create-java-project branch from cc8d3b7 to dcaa5ef Compare November 8, 2017 08:23
@jdneo
Copy link
Member Author

jdneo commented Nov 10, 2017

Close this PR since the code structure has changed largely. See #66

@jdneo jdneo closed this Nov 10, 2017
@jdneo jdneo deleted the cs-create-java-project branch February 5, 2018 09:26
@github-actions github-actions bot locked and limited conversation to collaborators Jan 16, 2021
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants